Commit 800f0de7 authored by Ted Lemon's avatar Ted Lemon
Browse files

Add support for functions, as well as arithmetic operators.

parent 56a7da7d
......@@ -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: */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment