]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Add support for functions, as well as arithmetic operators.
authorTed Lemon <source@isc.org>
Tue, 15 Feb 2000 19:39:48 +0000 (19:39 +0000)
committerTed Lemon <source@isc.org>
Tue, 15 Feb 2000 19:39:48 +0000 (19:39 +0000)
common/tree.c

index 96f483df0a918a2e08f6eb9f7ccc36f25c8baa94..c5590059ca52e9a5cdd5ebb69ebc86a5761051df 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: tree.c,v 1.76 2000/02/05 17:45:20 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: tree.c,v 1.77 2000/02/15 19:39:48 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -457,7 +457,7 @@ int evaluate_expression (result, packet, lease,
                }
 
                arg = expr -> data.funcall.arglist;
-               s = binding -> value -> value.fundef.args;
+               s = binding -> value -> value.fundef -> args;
                while (arg && s) {
                        nb = dmalloc (sizeof *nb, MDL);
                        if (!nb) {
@@ -499,7 +499,7 @@ int evaluate_expression (result, packet, lease,
                ns -> outer = scope;
                if (execute_statements
                    (packet, lease, in_options, cfg_options, ns,
-                    binding -> value -> value.fundef.statements)) {
+                    binding -> value -> value.fundef -> statements)) {
                        if (ns -> bindings && ns -> bindings -> name) {
                            binding_value_reference (result,
                                                     ns -> bindings -> value,
@@ -511,6 +511,12 @@ int evaluate_expression (result, packet, lease,
                        status = 0;
                binding_scope_dereference (&ns, MDL);
                return status;
+       } else if (expr -> op == expr_funcall) {
+               if (!binding_value_allocate (&bv, MDL))
+                       return 0;
+               bv -> type = binding_function;
+               fundef_reference (&bv -> value.fundef, expr -> data.func, MDL);
+               return 1;
         } else if (is_boolean_expression (expr)) {
                if (!binding_value_allocate (&bv, MDL))
                        return 0;
@@ -823,6 +829,11 @@ int evaluate_dns_expression (result, packet, lease, in_options,
              case expr_const_int:
              case expr_lease_time:
              case expr_dns_transaction:
+             case expr_add:
+             case expr_subtract:
+             case expr_multiply:
+             case expr_divide:
+             case expr_remainder:
                log_error ("Numeric opcode in evaluate_dns_expression: %d",
                      expr -> op);
                return 0;
@@ -1107,6 +1118,11 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
              case expr_const_int:
              case expr_lease_time:
              case expr_dns_transaction:
+             case expr_add:
+             case expr_subtract:
+             case expr_multiply:
+             case expr_divide:
+             case expr_remainder:
                log_error ("Numeric opcode in evaluate_boolean_expression: %d",
                      expr -> op);
                return 0;
@@ -1119,6 +1135,10 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
                      expr -> op);
                return 0;
 
+             case expr_function:
+               log_error ("function definition in evaluate_boolean_expr");
+               return 0;
+
              case expr_arg:
                break;
        }
@@ -1903,6 +1923,11 @@ int evaluate_data_expression (result, packet, lease,
              case expr_const_int:
              case expr_lease_time:
              case expr_dns_transaction:
+             case expr_add:
+             case expr_subtract:
+             case expr_multiply:
+             case expr_divide:
+             case expr_remainder:
                log_error ("Numeric opcode in evaluate_data_expression: %d",
                      expr -> op);
                return 0;
@@ -1914,8 +1939,13 @@ int evaluate_data_expression (result, packet, lease,
                log_error ("dns update opcode in evaluate_data_expression: %d",
                      expr -> op);
                return 0;
-                     case expr_arg:
-                       break;
+
+             case expr_function:
+               log_error ("function definition in evaluate_data_expression");
+               return 0;
+
+             case expr_arg:
+               break;
        }
 
        log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op);
@@ -1943,6 +1973,7 @@ int evaluate_numeric_expression (result, packet, lease,
        struct expression *cur, *next;
        struct binding *binding;
        struct binding_value *bv;
+       unsigned long ileft, iright;
 
        switch (expr -> op) {
              case expr_check:
@@ -2125,8 +2156,8 @@ int evaluate_numeric_expression (result, packet, lease,
              case expr_funcall:
                bv = (struct binding_value *)0;
                status = evaluate_expression (&bv, packet, lease,
-                                         in_options, cfg_options,
-                                         scope, expr);
+                                             in_options, cfg_options,
+                                             scope, expr);
                if (status) {
                        if (bv -> type != binding_numeric)
                                log_error ("%s() returned type %d in %s.",
@@ -2143,6 +2174,111 @@ int evaluate_numeric_expression (result, packet, lease,
 #endif
                break;
 
+             case expr_add:
+               sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    in_options, cfg_options,
+                                                    scope,
+                                                    expr -> data.and [0]);
+               sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     in_options, cfg_options,
+                                                     scope,
+                                                     expr -> data.and [1]);
+
+#if defined (DEBUG_EXPRESSIONS)
+               log_debug ("num: %d + %d = %d",
+                     ileft, iright,
+                     ((sleft && sright) ? (ileft + iright) : 0));
+#endif
+               if (sleft && sright) {
+                       *result = ileft + iright;
+                       return 1;
+               }
+               return 0;
+
+             case expr_subtract:
+               sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    in_options, cfg_options,
+                                                    scope,
+                                                    expr -> data.and [0]);
+               sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     in_options, cfg_options,
+                                                     scope,
+                                                     expr -> data.and [1]);
+
+#if defined (DEBUG_EXPRESSIONS)
+               log_debug ("num: %d - %d = %d",
+                     ileft, iright,
+                     ((sleft && sright) ? (ileft - iright) : 0));
+#endif
+               if (sleft && sright) {
+                       *result = ileft - iright;
+                       return 1;
+               }
+               return 0;
+
+             case expr_multiply:
+               sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    in_options, cfg_options,
+                                                    scope,
+                                                    expr -> data.and [0]);
+               sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     in_options, cfg_options,
+                                                     scope,
+                                                     expr -> data.and [1]);
+
+#if defined (DEBUG_EXPRESSIONS)
+               log_debug ("num: %d * %d = %d",
+                     ileft, iright,
+                     ((sleft && sright) ? (ileft * iright) : 0));
+#endif
+               if (sleft && sright) {
+                       *result = ileft * iright;
+                       return 1;
+               }
+               return 0;
+
+             case expr_divide:
+               sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    in_options, cfg_options,
+                                                    scope,
+                                                    expr -> data.and [0]);
+               sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     in_options, cfg_options,
+                                                     scope,
+                                                     expr -> data.and [1]);
+
+#if defined (DEBUG_EXPRESSIONS)
+               log_debug ("num: %d / %d = %d",
+                     ileft, iright,
+                     ((sleft && sright && iright) ? (ileft / iright) : 0));
+#endif
+               if (sleft && sright && iright) {
+                       *result = ileft / iright;
+                       return 1;
+               }
+               return 0;
+
+             case expr_remainder:
+               sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    in_options, cfg_options,
+                                                    scope,
+                                                    expr -> data.and [0]);
+               sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     in_options, cfg_options,
+                                                     scope,
+                                                     expr -> data.and [1]);
+
+#if defined (DEBUG_EXPRESSIONS)
+               log_debug ("num: %d %% %d = %d",
+                     ileft, iright,
+                     ((sleft && sright && iright) ? (ileft % iright) : 0));
+#endif
+               if (sleft && sright && iright) {
+                       *result = ileft % iright;
+                       return 1;
+               }
+               return 0;
+
              case expr_ns_add:
              case expr_ns_delete:
              case expr_ns_exists:
@@ -2151,6 +2287,10 @@ int evaluate_numeric_expression (result, packet, lease,
                      expr -> op);
                return 0;
 
+             case expr_function:
+               log_error ("function definition in evaluate_numeric_expr");
+               return 0;
+
              case expr_arg:
                break;
        }
@@ -2298,6 +2438,11 @@ void expression_dereference (eptr, file, line)
              case expr_concat:
              case expr_and:
              case expr_or:
+             case expr_add:
+             case expr_subtract:
+             case expr_multiply:
+             case expr_divide:
+             case expr_remainder:
                if (expr -> data.equal [0])
                        expression_dereference (&expr -> data.equal [0],
                                                file, line);
@@ -2456,6 +2601,10 @@ void expression_dereference (eptr, file, line)
                                                file, line);
                break;
 
+             case expr_function:
+               fundef_dereference (&expr -> data.func, file, line);
+               break;
+
                /* No subexpressions. */
              case expr_leased_address:
              case expr_lease_time:
@@ -2609,6 +2758,7 @@ static int op_val (op)
              case expr_ns_not_exists:
              case expr_arg:
              case expr_funcall:
+             case expr_function:
                return 100;
 
              case expr_equal:
@@ -2616,9 +2766,14 @@ static int op_val (op)
                return 3;
 
              case expr_and:
+             case expr_multiply:
+             case expr_divide:
+             case expr_remainder:
                return 1;
 
              case expr_or:
+             case expr_add:
+             case expr_subtract:
                return 2;
        }
        return 100;
@@ -2679,6 +2834,7 @@ enum expression_context op_context (op)
              case expr_dns_transaction:
              case expr_arg:
              case expr_funcall:
+             case expr_function:
                return context_any;
 
              case expr_equal:
@@ -2690,6 +2846,13 @@ enum expression_context op_context (op)
 
              case expr_or:
                return context_boolean;
+
+             case expr_add:
+             case expr_subtract:
+             case expr_multiply:
+             case expr_divide:
+             case expr_remainder:
+               return context_numeric;
        }
        return context_any;
 }
@@ -2803,6 +2966,26 @@ int write_expression (file, expr, col, indent, firstp)
                col = token_print_indent (file, col, indent, "", "", ")");
                break;
 
+             case expr_add:
+               s = "+";
+               goto binary;
+
+             case expr_subtract:
+               s = "-";
+               goto binary;
+
+             case expr_multiply:
+               s = "*";
+               goto binary;
+
+             case expr_divide:
+               s = "/";
+               goto binary;
+
+             case expr_remainder:
+               s = "%";
+               goto binary;
+
              case expr_and:
                s = "and";
                goto binary;
@@ -3198,4 +3381,57 @@ int binding_scope_dereference (ptr, file, line)
        return 1;
 }
 
+int fundef_dereference (ptr, file, line)
+       struct fundef **ptr;
+       const char *file;
+       int line;
+{
+       struct fundef *bp;
+       struct string_list *sp, *next;
+
+       if (!ptr) {
+               log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+               abort ();
+#else
+               return 0;
+#endif
+       }
+
+       if (!bp) {
+               log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+               abort ();
+#else
+               return 0;
+#endif
+       }
+
+       bp -> refcnt--;
+       rc_register (file, line, ptr, bp, bp -> refcnt);
+       if (bp -> refcnt < 0) {
+               log_error ("%s(%d): negative refcnt!", file, line);
+#if defined (DEBUG_RC_HISTORY)
+               dump_rc_history ();
+#endif
+#if defined (POINTER_DEBUG)
+               abort ();
+#else
+               return 0;
+#endif
+       }
+       if (!bp -> refcnt) {
+               for (sp = bp -> args; sp; sp = next) {
+                       next = sp -> next;
+                       dfree (sp, file, line);
+               }
+               if (bp -> statements)
+                       executable_statement_dereference (&bp -> statements,
+                                                         file, line);
+               dfree (bp, file, line);
+       }
+       *ptr = (struct fundef *)0;
+       return 1;
+}
+
 /* vim: set tabstop=8: */