diff host/libcdl/expr.cxx @ 159:511f4dc167f6

Merge from eCos master repository on 2001-05-18-01:30:05-BST
author jlarmour
date Fri, 18 May 2001 06:32:28 +0000
parents 6ed91473a1cd
children 0d2b193a635f
line wrap: on
line diff
--- a/host/libcdl/expr.cxx
+++ b/host/libcdl/expr.cxx
@@ -10,7 +10,7 @@
 //####COPYRIGHTBEGIN####
 //                                                                          
 // ----------------------------------------------------------------------------
-// Copyright (C) 1999, 2000 Red Hat, Inc.
+// Copyright (C) 1999, 2000, 2001 Red Hat, Inc.
 //
 // This file is part of the eCos host tools.
 //
@@ -82,19 +82,31 @@ CdlEvalContext::CdlEvalContext(CdlTransa
     CYG_REPORT_FUNCARG4XV(this, transaction_arg, node_arg, property_arg);
 
     transaction = transaction_arg;
+    
+    if ((0 == property_arg) && (0 != transaction)) {
+        CdlConflict conflict = transaction->get_conflict();
+        if (0 != conflict) {
+            property_arg = conflict->get_property();
+        }
+    }
+    property    = property_arg;
+    
+    if ((0 == node_arg) && (0 != transaction)) {
+        CdlConflict conflict = transaction->get_conflict();
+        if (0 != conflict) {
+            node_arg = conflict->get_node();
+        }
+    }
     node        = node_arg;
-    property    = property_arg;
+    
     if (0 == toplevel_arg) {
         if (0 != transaction) {
-            toplevel = transaction->get_toplevel();
+            toplevel_arg = transaction->get_toplevel();
         } else if (0 != node) {
-            toplevel = node->get_toplevel();
-        } else {
-            toplevel = toplevel_arg;
+            toplevel_arg = node->get_toplevel();
         }
-    } else {
-        toplevel = toplevel_arg;
     }
+    toplevel = toplevel_arg;
     
     cdlevalcontext_cookie = CdlEvalContext_Magic;
     CYGDBG_MEMLEAK_CONSTRUCTOR();
@@ -219,7 +231,11 @@ enum token {
     T_BitOr             = 26,   // |
     T_And               = 27,   // &&
     T_Or                = 28,   // ||
-    T_Colon             = 29    // : (in a conditional)
+    T_Colon             = 29,   // : (in a conditional)
+    T_StringConcat      = 30,   // .
+    T_Function          = 31,   // is_substr etc.
+    T_Comma             = 32    // , (inside a function)
+    
 };
 
 //}}}
@@ -236,6 +252,7 @@ static std::string      current_referenc
 static cdl_int          current_int             = 0;
 static double           current_double          = 0.0;
 static CdlValueFormat   current_format          = CdlValueFormat_Default;
+static int              current_function_id     = 0;
 
 //}}}
 //{{{  Character access                 
@@ -345,8 +362,8 @@ token_to_binary_expr_op()
       case T_BitOr:             result = CdlExprOp_BitOr; break;
       case T_And:               result = CdlExprOp_And; break;
       case T_Or:                result = CdlExprOp_Or; break;
-
-      default: result = CdlExprOp_Invalid; break;
+      case T_StringConcat:      result = CdlExprOp_StringConcat; break;
+      default:                  result = CdlExprOp_Invalid; break;
     }
     
     CYG_REPORT_RETVAL(result);
@@ -379,7 +396,7 @@ token_to_expr_op()
         case T_Tilde:           result = CdlExprOp_BitNot; break;
         case T_Questionmark:
         case T_Colon:           result = CdlExprOp_Cond; break; // best guess
-            
+        case T_Function:        result = CdlExprOp_Function; break;
         case T_OpenBracket:
         case T_CloseBracket:
         case T_Invalid:
@@ -441,6 +458,8 @@ token_to_string()
       case T_And:               result = "and operator &&"; break;
       case T_Or:                result = "or operator ||"; break;
       case T_Colon:             result = "colon"; break;
+      case T_StringConcat:      result = "string concatenation operator ."; break;
+      case T_Function:          result = std::string("function call ") + CdlFunction::get_name(current_function_id); break;
       case T_Invalid:
       default:                  result = "<invalid token>"; break;
     }
@@ -722,21 +741,22 @@ process_number()
 }
 
 //}}}
-//{{{  process_reference()              
-
-// The start of a reference has been detected.
-// A reference name must be a valid C preprocessor name, so the
-// only characters allowed are underscore, upper and lower case
-// characters, and digits. The first character cannot be a digit,
-// but that has been checked already.
+//{{{  process_alphanumeric()           
+
+// The start of an alphanumeric sequence has been detected. This may
+// be a reference, a function call, or an operator like eq or to. All
+// such sequences must be a valid C preprocessor name, so the only
+// characters allowed are underscore, upper and lower case characters,
+// and digits. The first character cannot be a digit, but that has
+// been checked already.
 //
 // Some care has to be taken with locale's, the C library may decide
 // that a character is a letter even though the same character is not
 // valid as far as the preprocessor is concerned.
 static void
-process_reference()
+process_alphanumeric()
 {
-    CYG_REPORT_FUNCNAME("process_reference");
+    CYG_REPORT_FUNCNAME("process_alphanumeric");
 
     do {
        current_reference += (char) current_char;
@@ -745,12 +765,42 @@ process_reference()
              (('a' <= current_char) && (current_char <= 'z')) ||
              (('A' <= current_char) && (current_char <= 'Z')));
 
-    current_token = T_Reference;
-
     CYG_REPORT_RETURN();
 }
 
 //}}}
+//{{{  process_special()                
+
+// Usually an alphanumeric sequence of characters is a reference, e.g.
+// CYGPKG_KERNEL. However there are only so many special characters
+// available so some operators are implemented as a sequence, e.g. 
+// "to". CDL also supports functions like is_substr().
+//
+// The data will have been collected into the current_reference string
+// by a call to process_alphanumeric().
+
+static bool
+process_special()
+{
+    CYG_REPORT_FUNCNAMETYPE("process_special", "special %d");
+    bool result = false;
+    
+    if ("to" == current_reference) {
+        current_token  = T_Range;
+        result = true;
+    } else if (CdlFunction::is_function(current_reference.c_str(), current_function_id)) {
+        current_token           = T_Function;
+        result = true;
+    }
+
+    if (result) {
+        current_reference = "";
+    }
+    CYG_REPORT_RETVAL(result);
+    return result;
+}
+
+//}}}
 
 //}}}
 //{{{  next_token()                     
@@ -770,6 +820,7 @@ next_token()
     current_int         = 0;
     current_double      = 0.0;
     current_format      = CdlValueFormat_Default;
+    current_function_id = 0;
 
     // Skip leading white space. This includes newlines, tabs, etc,
     // consider the case of:
@@ -931,10 +982,21 @@ next_token()
           next_char();
           break;
 
+      case '.':
+          current_token = T_StringConcat;
+          next_char();
+          break;
+
+      case ',':
+          current_token = T_Comma;
+          next_char();
+          break;
+        
       default:
           // String constants have been handled already. The only
-          // valid tokens that are left are numbers, references and
-          // the rang eoperator.
+          // valid tokens that are left are numbers, references,
+          // "specials" such as the range and string equality
+          // operators, and functions.
           //
           // Numbers should begin with a digit (plus and minus are
           // tokenized separately).
@@ -948,11 +1010,8 @@ next_token()
           } else if (('_' == current_char) ||
                      (('a' <= current_char) && (current_char <= 'z')) ||
                      (('A' <= current_char) && (current_char <= 'Z'))) {
-              process_reference();
-              if ("to" == current_reference) {
-                  current_reference = "";
-                  current_token  = T_Range;
-              } else {
+              process_alphanumeric();
+              if (!process_special()) {
                   current_token = T_Reference;
               }
           } else {
@@ -1009,13 +1068,13 @@ initialise_tokenisation(std::string data
 //   <eq>           ::= <comp>   [<eq op>     <comp>]          == !=
 //   <comp>         ::= <shift>  [<comp op>   <shift>]         < <= > >=
 //   <shift>        ::= <add>    [<shift op>  <add>]           << >>
-//   <add>          ::= <mult>   [<add op>    <mult>]          + -
+//   <add>          ::= <mult>   [<add op>    <mult>]          + - .
 //   <mult>         ::= <unary>  [<mult op>   <unary>]         * / %
 //   <unary>        ::= -<unary> | +<unary> | !<unary> | *<unary> | ?<unary> |
 //                      ~<unary> |
 //                      <string constant> | <integer constant> |
 //                      <double constant> | <reference> |
-//                      ( <expression> )
+//                      ( <expression> ) | <function>
 //
 // There are separate functions for each of these terms.
 
@@ -1064,6 +1123,52 @@ current_subexpression(CdlExpression expr
 }
 
 static void
+parse_function(CdlExpression expr)
+{
+    CYG_REPORT_FUNCNAME("parse_function");
+    CYG_REPORT_FUNCARG1XV(expr);
+    CYG_PRECONDITION_CLASSC(expr);
+
+    CdlSubexpression subexpr;
+    subexpr.op          = CdlExprOp_Function;
+    subexpr.func        = current_function_id;
+
+    int number_of_args  = CdlFunction::get_args_count(current_function_id);
+    CYG_ASSERTC((0 < number_of_args) && (number_of_args <= CdlFunction_MaxArgs));
+    std::string name    = current_reference;
+
+    // check for the opening bracket: xyzzy(arg1, arg2)
+    next_token();
+    if (T_OpenBracket != current_token) {
+        throw CdlParseException(std::string("Expected opening bracket after function ") + name + "\n" + get_error_location());
+    }
+    next_token();
+
+    int i;
+    for (i = 0; i < number_of_args; i++) {
+        parse_expression(expr);
+        subexpr.args[i] = expr->first_subexpression;
+        if (i < (number_of_args - 1)) {
+            if (T_Comma != current_token) {
+                throw CdlParseException(std::string("Expected comma between arguments in function ") +
+                                        name + "\n" + get_error_location());
+            }
+            next_token();
+        }
+    }
+    if (T_CloseBracket != current_token) {
+        throw CdlParseException(std::string("Expected closing bracket after function ") + name + "\n" + get_error_location());
+    }
+    next_token();
+    
+    // Allow the function implementation to check its arguments if it is so inclined.
+    CdlFunction::check(expr, subexpr);
+    
+    push_subexpression(expr, subexpr);
+    CYG_REPORT_RETURN();
+}
+
+static void
 parse_unary(CdlExpression expr)
 {
     CYG_REPORT_FUNCNAME("parse_operand");
@@ -1078,6 +1183,12 @@ parse_unary(CdlExpression expr)
         // This warrants a special case
         throw CdlParseException("End of expression reached when expecting an operand.\n" + get_error_location());
       }
+
+      case T_Function :
+      {
+          parse_function(expr);
+          break;
+      }
       
       case T_Reference :
       {
@@ -1247,10 +1358,14 @@ parse_add(CdlExpression expr)
     CYG_REPORT_FUNCNAME("parse_add");
     
     parse_multiply(expr);
-    while ((T_Plus == current_token) || (T_Minus == current_token)) {
+    while ((T_Plus == current_token)  ||
+           (T_Minus == current_token) ||
+           (T_StringConcat == current_token)) {
 
         CdlSubexpression subexpr;
-        subexpr.op = (T_Plus == current_token) ? CdlExprOp_Add : CdlExprOp_Subtract;
+        subexpr.op = (T_Plus == current_token) ? CdlExprOp_Add :
+                     (T_Minus == current_token) ? CdlExprOp_Subtract :
+                     CdlExprOp_StringConcat;
         subexpr.lhs_index = expr->first_subexpression;
         
         next_token();
@@ -1317,7 +1432,8 @@ parse_equals(CdlExpression expr)
     CYG_REPORT_FUNCNAME("parse_equals");
     
     parse_comparison(expr);
-    while ((T_Equal == current_token) || (T_NotEqual == current_token)) {
+    while ((T_Equal == current_token) ||
+           (T_NotEqual == current_token)) {
 
         CdlSubexpression subexpr;
         subexpr.op = (T_Equal == current_token) ? CdlExprOp_Equal : CdlExprOp_NotEqual;
@@ -1535,6 +1651,11 @@ evaluate_subexpr(CdlEvalContext& context
         result = subexpr.constants;
         break;
     }
+    case CdlExprOp_Function :
+    {
+        CdlFunction::eval(context, expr, subexpr, result);
+        break;
+    }
     case CdlExprOp_Reference :
     {
         // This expression may be happening in the context of a particular
@@ -2045,6 +2166,16 @@ evaluate_subexpr(CdlEvalContext& context
         }
         break;
     }
+    case CdlExprOp_StringConcat :
+    {
+        // a . b
+        CdlSimpleValue lhs;
+        CdlSimpleValue rhs;
+        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);
+        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);
+        result = lhs.get_value() + rhs.get_value();
+        break;
+    }
 
     default:
         break;
@@ -2067,6 +2198,19 @@ CdlExpressionBody::eval_internal(CdlEval
     CYG_REPORT_RETURN();
 }
 
+void
+CdlExpressionBody::eval_subexpression(CdlEvalContext& context, int index, CdlSimpleValue& result)
+{
+    CYG_REPORT_FUNCNAME("CdlExpression::eval_subexpression)");
+    CYG_REPORT_FUNCARG4XV(this, &context, index, &result);
+    CYG_INVARIANT_THISC(CdlExpressionBody);
+    CYG_PRECONDITION_CLASSOC(context);
+
+    evaluate_subexpr(context, this, index, result);
+    
+    CYG_REPORT_RETURN();
+}
+
 //}}}
 
 //{{{  CdlExpression