]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Add support for function calls and typed variables.
authorTed Lemon <source@isc.org>
Sat, 5 Feb 2000 18:07:17 +0000 (18:07 +0000)
committerTed Lemon <source@isc.org>
Sat, 5 Feb 2000 18:07:17 +0000 (18:07 +0000)
common/execute.c
common/parse.c

index 9c499477bf73e86b511a626316e7269648b63cf4..d6eb292ee98f44933b97174bef2e1954735c4415 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: execute.c,v 1.28 2000/02/02 20:01:41 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: execute.c,v 1.29 2000/02/05 18:07:17 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -132,51 +132,10 @@ int execute_statements (packet, lease, in_options, out_options, scope,
                        break;
 
                      case eval_statement:
-                       if (is_boolean_expression (r -> data.eval)) {
-                               status = (evaluate_boolean_expression
-                                         (&result, packet, lease, in_options,
-                                          out_options, scope,
-                                          r -> data.eval));
-                       } else if (is_numeric_expression (r -> data.eval)) {
-                               status = (evaluate_numeric_expression
-                                         (&num, packet, lease, in_options,
-                                          out_options, scope,
-                                          r -> data.eval));
-                       } else if (is_data_expression  (r -> data.eval)) {
-                               memset (&ds, 0, sizeof ds);
-                               status = (evaluate_data_expression
-                                         (&ds, packet, lease, in_options,
-                                          out_options, scope,
-                                          r -> data.eval));
-                               if (status && ds.data)
-                                       data_string_forget (&ds, MDL);
-                       } else if (is_dns_expression (r -> data.eval)) {
-#if defined (NSUPDATE)
-                               ns_updrec *nut;
-                               nut = 0;
-                               status = (evaluate_dns_expression
-                                         (&nut, packet, lease, in_options,
-                                          out_options, scope,
-                                          r -> data.eval));
-                               if (status) {
-                                       if (nut -> r_data) {
-                                               dfree (nut -> r_data, MDL);
-                                               nut -> r_data =
-                                                       (unsigned char *)0;
-                                       }
-                                       if (nut -> r_dname) {
-                                               dfree (nut -> r_dname, MDL);
-                                               nut -> r_dname = (char *)0;
-                                       }
-                                       minires_freeupdrec (nut);
-                               }
-#endif
-                       } else {
-                               log_error ("%s: invalid expression type: %d",
-                                          "execute_statements",
-                                          r -> data.eval -> op);
-                       }
-
+                       status = evaluate_expression
+                               ((struct binding_value **)0,
+                                packet, lease, in_options,
+                                out_options, scope, r -> data.eval);
 #if defined (DEBUG_EXPRESSIONS)
                        log_debug ("exec: evaluate: %s",
                                   (status "succeeded" : "failed"));
@@ -235,11 +194,6 @@ int execute_statements (packet, lease, in_options, out_options, scope,
                        break;
 
                      case set_statement:
-                       memset (&ds, 0, sizeof ds);
-                       status = (evaluate_data_expression
-                                 (&ds, packet, lease, in_options, out_options,
-                                  scope, r -> data.set.expr));
-
                        binding = find_binding (scope, r -> data.set.name);
                        if (!binding && status) {
                                binding = dmalloc (sizeof *binding, MDL);
@@ -268,47 +222,39 @@ int execute_statements (packet, lease, in_options, out_options, scope,
                                }
                        }
                        if (binding) {
-                               if (binding -> value.data)
-                                   data_string_forget (&binding -> value,
-                                                       MDL);
-                               if (status)
-                                   data_string_copy (&binding -> value, &ds,
-                                                     MDL);
+                               if (binding -> value)
+                                       binding_value_dereference
+                                               (&binding -> value, MDL);
+                               status = (evaluate_expression
+                                         (&binding -> value, packet, lease,
+                                          in_options, out_options,
+                                          scope, r -> data.set.expr));
                        }
-                       if (status)
-                           data_string_forget (&ds, MDL);
 #if defined (DEBUG_EXPRESSIONS)
-                       log_debug ("exec: set %s = %s", r -> data.set.name,
-                                  (status && binding
-                                   ? print_hex_1 (binding -> value.len,
-                                                  binding -> value.data, 50)
-                                   : "NULL"));
+                       log_debug ("exec: set %s%s", r -> data.set.name,
+                                  (binding && status ? "" : " (failed)"));
 #endif
                        break;
 
                      case unset_statement:
                        binding = find_binding (scope, r -> data.unset);
                        if (binding) {
-                               if (binding -> value.data)
-                                       data_string_forget (&binding -> value,
-                                                           MDL);
+                               if (binding -> value)
+                                       binding_value_dereference
+                                               (&binding -> value, MDL);
                                status = 1;
                        } else
                                status = 0;
 #if defined (DEBUG_EXPRESSIONS)
                        log_debug ("exec: unset %s: %s", r -> data.unset,
-                                  (status ? "found" : "NULL"));
+                                  (status ? "found" : "not found"));
 #endif
                        break;
 
                      case let_statement:
-                       memset (&ds, 0, sizeof ds);
-                       status = (evaluate_data_expression
-                                 (&ds, packet, lease, in_options, out_options,
-                                  scope, r -> data.let.expr));
-
                        ns = (struct binding_scope *)0;
                        binding_scope_allocate (&ns, MDL);
+                       e = r;
 
                      next_let:
                        if (ns) {
@@ -319,11 +265,11 @@ int execute_statements (packet, lease, in_options, out_options, scope,
                                } else {
                                    binding -> name =
                                            dmalloc (strlen
-                                                    (r -> data.let.name + 1),
+                                                    (e -> data.let.name + 1),
                                                     MDL);
                                    if (binding -> name)
                                        strcpy (binding -> name,
-                                               r -> data.let.name);
+                                               e -> data.let.name);
                                    else {
                                        dfree (binding, MDL);
                                        binding = (struct binding *)0;
@@ -331,31 +277,29 @@ int execute_statements (packet, lease, in_options, out_options, scope,
                                    }
                                }
                        }
-                       if (ns && binding && status) {
-                               data_string_copy (&binding -> value, &ds, MDL);
+                       if (ns && binding) {
+                               status = (evaluate_expression
+                                         (&binding -> value, packet, lease,
+                                          in_options, out_options,
+                                          scope, e -> data.set.expr));
                                binding -> next = ns -> bindings;
                                ns -> bindings = binding;
                        }
 
-                       if (status)
-                           data_string_forget (&ds, MDL);
 #if defined (DEBUG_EXPRESSIONS)
-                       log_debug ("exec: let %s = %s", r -> data.let.name,
-                                  (status && binding
-                                   ? print_hex_1 (binding -> value.len,
-                                                  binding -> value.data, 50)
-                                   : "NULL"));
+                       log_debug ("exec: let %s%s", e -> data.let.name,
+                                  (binding && status ? "" : "failed"));
 #endif
-                       if (!r -> data.let.statements) {
-                       } else if (r -> data.let.statements -> op ==
+                       if (!e -> data.let.statements) {
+                       } else if (e -> data.let.statements -> op ==
                                   let_statement) {
-                               r = r -> data.let.statements;
+                               e = e -> data.let.statements;
                                goto next_let;
                        } else if (ns) {
                                ns -> outer = scope;
                                execute_statements
                                      (packet, lease, in_options, out_options,
-                                      ns, r -> data.let.statements);
+                                      ns, e -> data.let.statements);
                        }
                        if (ns)
                                binding_scope_dereference (&ns, MDL);
index e0535935213b94581e72a207ddd1bcac63015946..7d4f8264a62206d855d06865d0e87e5f4e7338c0 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: parse.c,v 1.62 2000/02/02 17:10:38 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: parse.c,v 1.63 2000/02/05 18:04:47 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -1810,7 +1810,9 @@ int parse_boolean_expression (expr, cfile, lose)
                               (struct expression **)0, expr_none))
                return 0;
 
-       if (!is_boolean_expression (*expr)) {
+       if (!is_boolean_expression (*expr) &&
+           (*expr) -> op != expr_variable_reference &&
+           (*expr) -> op != expr_funcall) {
                parse_warn (cfile, "Expecting a boolean expression.");
                *lose = 1;
                expression_dereference (expr, MDL);
@@ -1845,7 +1847,9 @@ int parse_data_expression (expr, cfile, lose)
                               (struct expression **)0, expr_none))
                return 0;
 
-       if (!is_data_expression (*expr)) {
+       if (!is_data_expression (*expr) &&
+           (*expr) -> op != expr_variable_reference &&
+           (*expr) -> op != expr_funcall) {
                parse_warn (cfile, "Expecting a data expression.");
                *lose = 1;
                return 0;
@@ -1869,7 +1873,9 @@ int parse_numeric_expression (expr, cfile, lose)
                               (struct expression **)0, expr_none))
                return 0;
 
-       if (!is_numeric_expression (*expr)) {
+       if (!is_numeric_expression (*expr) &&
+           (*expr) -> op != expr_variable_reference &&
+           (*expr) -> op != expr_funcall) {
                parse_warn (cfile, "Expecting a numeric expression.");
                *lose = 1;
                return 0;
@@ -1901,7 +1907,9 @@ int parse_dns_expression (expr, cfile, lose)
                               (struct expression **)0, expr_none))
                return 0;
 
-       if (!is_dns_expression (*expr)) {
+       if (!is_dns_expression (*expr) &&
+           (*expr) -> op != expr_variable_reference &&
+           (*expr) -> op != expr_funcall) {
                parse_warn (cfile, "Expecting a dns update subexpression.");
                *lose = 1;
                return 0;
@@ -1921,12 +1929,14 @@ int parse_non_binary (expr, cfile, lose, context)
        const char *val;
        struct collection *col;
        struct option *option;
-       struct expression *nexp;
+       struct expression *nexp, **ep;
        int known;
        enum expr_op opcode;
        const char *s;
+       char *cptr;
        struct executable_statement *stmt;
        int i;
+       unsigned long u;
 
        token = peek_token (&val, cfile);
 
@@ -2274,41 +2284,48 @@ int parse_non_binary (expr, cfile, lose, context)
                }
                        
                if (!strcasecmp (val, "a"))
-                       i = T_A;
+                       u = T_A;
                else if (!strcasecmp (val, "ptr"))
-                       i = T_PTR;
+                       u = T_PTR;
                else if (!strcasecmp (val, "mx"))
-                       i = T_MX;
+                       u = T_MX;
                else if (!strcasecmp (val, "cname"))
-                       i = T_CNAME;
+                       u = T_CNAME;
                else if (!strcasecmp (val, "TXT"))
-                       i = T_TXT;
+                       u = T_TXT;
                else {
                        parse_warn (cfile, "unexpected rrtype: %s", val);
                        goto badnsupdate;
                }
 
+               s = (opcode == expr_ns_add
+                    ? "old-dns-update"
+                    : "old-dns-delete");
+               cptr = dmalloc (strlen (s) + 1, MDL);
+               if (!cptr)
+                       log_fatal ("can't allocate name for %s", s);
+               strcpy (cptr, s);
                if (!expression_allocate (expr, MDL))
                        log_fatal ("can't allocate expression");
-#if 0
                (*expr) -> op = expr_funcall;
-               (*expr) -> data.funcall.context = context_boolean;
-               (*expr) -> data.funcall.name = 
+               (*expr) -> data.funcall.name = cptr;
 
-               if (!make_let (&(*expr) -> data.funcall.statements, "rrtype"))
-                       log_fatal ("can't allocate rrtype let.");
-               stmt = (*expr) -> data.funcall.statements;
-               if (!make_const_int (stmt -> data.let.value, i))
+               /* Fake up a function call. */
+               ep = &(*expr) -> data.funcall.arglist;
+               if (!expression_allocate (ep, MDL))
+                       log_fatal ("can't allocate expression");
+               (*ep) -> op = expr_arg;
+               if (!make_const_int (&(*ep) -> data.arg.val, u))
                        log_fatal ("can't allocate rrtype value.");
 
                token = next_token (&val, cfile);
                if (token != COMMA)
                        goto nocomma;
-
-               if (!make_let (&stmt -> data.let.statements, "rrname"))
-                       log_fatal ("can't allocate rrname let.");
-               stmt = stmt -> data.let.statements;
-               if (!(parse_data_expression (&stmt -> data.let.expr,
+               ep = &((*ep) -> data.arg.next);
+               if (!expression_allocate (ep, MDL))
+                       log_fatal ("can't allocate expression");
+               (*ep) -> op = expr_arg;
+               if (!(parse_data_expression (&(*ep) -> data.arg.val,
                                             cfile, lose)))
                        goto nodata;
 
@@ -2316,10 +2333,11 @@ int parse_non_binary (expr, cfile, lose, context)
                if (token != COMMA)
                        goto nocomma;
 
-               if (!make_let (&stmt -> data.let.statements, "rrdata"))
-                       log_fatal ("can't allocate rrname let.");
-               stmt = stmt -> data.let.statements;
-               if (!(parse_data_expression (&stmt -> data.let.expr,
+               ep = &((*ep) -> data.arg.next);
+               if (!expression_allocate (ep, MDL))
+                       log_fatal ("can't allocate expression");
+               (*ep) -> op = expr_arg;
+               if (!(parse_data_expression (&(*ep) -> data.arg.val,
                                             cfile, lose)))
                        goto nodata;
 
@@ -2328,18 +2346,18 @@ int parse_non_binary (expr, cfile, lose, context)
                        if (token != COMMA)
                                goto nocomma;
                        
-                       if (!make_let (&stmt -> data.let.statements, "ttl"))
-                               log_fatal ("can't allocate rrname let.");
-                       stmt = stmt -> data.let.statements;
-
-                       if (!(parse_numeric_expression
-                             (&stmt -> data.let.expr, cfile, lose))) {
+                       ep = &((*ep) -> data.arg.next);
+                       if (!expression_allocate (ep, MDL))
+                               log_fatal ("can't allocate expression");
+                       (*ep) -> op = expr_arg;
+                       if (!(parse_numeric_expression (&(*ep) -> data.arg.val,
+                                                       cfile, lose))) {
                                parse_warn (cfile,
                                            "expecting numeric expression.");
                                goto badnsupdate;
                        }
                }
-#endif
+
                token = next_token (&val, cfile);
                if (token != RPAREN)
                        goto norparen;
@@ -2885,14 +2903,59 @@ int parse_non_binary (expr, cfile, lose, context)
                if (token != NAME && token != NUMBER_OR_NAME)
                        return 0;
 
+               token = next_token (&val, cfile);
+
+               /* Save the name of the variable being referenced. */
+               cptr = dmalloc (strlen (val) + 1, MDL);
+               if (!cptr)
+                       log_fatal ("can't allocate variable name");
+               strcpy (cptr, val);
+
+               /* Simple variable reference, as far as we can tell. */
+               token = peek_token (&val, cfile);
+               if (token != LPAREN) {
+                       if (!expression_allocate (expr, MDL))
+                               log_fatal ("can't allocate expression");
+                       (*expr) -> op = expr_variable_reference;
+                       (*expr) -> data.variable = cptr;
+                       break;
+               }
+
                token = next_token (&val, cfile);
                if (!expression_allocate (expr, MDL))
                        log_fatal ("can't allocate expression");
-               (*expr) -> op = expr_variable_reference;
-               (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
-               if (!(*expr)->data.variable)
-                       log_fatal ("can't allocate variable name");
-               strcpy ((*expr) -> data.variable, val);
+               (*expr) -> op = expr_funcall;
+               (*expr) -> data.funcall.name = cptr;
+
+               /* Now parse the argument list. */
+               ep = &(*expr) -> data.funcall.arglist;
+               do {
+                       if (!expression_allocate (ep, MDL))
+                               log_fatal ("can't allocate expression");
+                       (*ep) -> op = expr_arg;
+                       if (!parse_expression (&(*ep) -> data.arg.val,
+                                              cfile, lose, context_any,
+                                              (struct expression **)0,
+                                              expr_none)) {
+                               if (!*lose) {
+                                       parse_warn (cfile,
+                                                   "expecting expression.");
+                                       *lose = 1;
+                               }
+                               skip_to_semi (cfile);
+                               expression_dereference (expr, MDL);
+                               return 0;
+                       }
+                       ep = &((*ep) -> data.arg.next);
+                       token = next_token (&val, cfile);
+               } while (token == COMMA);
+               if (token != RPAREN) {
+                       parse_warn (cfile, "Right parenthesis expected.");
+                       skip_to_semi (cfile);
+                       *lose = 1;
+                       expression_dereference (expr, MDL);
+                       return 0;
+               }
                break;
        }
        return 1;