3 Routines for manipulating parse trees... */
6 * Copyright (c) 1996-2000 Internet Software Consortium.
7 * Use is subject to license terms which appear in the file named
8 * ISC-LICENSE that should have accompanied this file when you
9 * received it. If a file named ISC-LICENSE did not accompany this
10 * file, or you are not sure the one you have is correct, you may
11 * obtain an applicable copy of the license at:
13 * http://www.isc.org/isc-license-1.0.html.
15 * This file is part of the ISC DHCP distribution. The documentation
16 * associated with this file is listed in the file DOCUMENTATION,
17 * included in the top-level directory of this release.
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
24 static char copyright
[] =
25 "$Id: tree.c,v 1.69 2000/01/26 14:55:35 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
29 #include <omapip/omapip_p.h>
31 struct binding_scope global_scope
;
33 static int do_host_lookup
PROTO ((struct data_string
*,
34 struct dns_host_entry
*));
40 pair foo
= (pair
)dmalloc (sizeof *foo
, MDL
);
42 log_fatal ("no memory for cons.");
48 int make_const_option_cache (oc
, buffer
, data
, len
, option
, file
, line
)
49 struct option_cache
**oc
;
50 struct buffer
**buffer
;
53 struct option
*option
;
63 bp
= (struct buffer
*)0;
64 if (!buffer_allocate (&bp
, len
, file
, line
)) {
65 log_error ("%s(%d): can't allocate buffer.",
71 if (!option_cache_allocate (oc
, file
, line
)) {
72 log_error ("%s(%d): can't allocate option cache.", file
, line
);
73 buffer_dereference (&bp
, file
, line
);
77 (*oc
) -> data
.len
= len
;
78 (*oc
) -> data
.data
= &bp
-> data
[0];
79 (*oc
) -> data
.terminated
= 0;
81 memcpy (&bp
-> data
[0], data
, len
);
82 (*oc
) -> option
= option
;
86 int make_host_lookup (expr
, name
)
87 struct expression
**expr
;
90 if (!expression_allocate (expr
, MDL
)) {
91 log_error ("No memory for host lookup tree node.");
94 (*expr
) -> op
= expr_host_lookup
;
95 if (!enter_dns_host (&((*expr
) -> data
.host_lookup
), name
)) {
96 expression_dereference (expr
, MDL
);
102 int enter_dns_host (dh
, name
)
103 struct dns_host_entry
**dh
;
106 /* XXX This should really keep a hash table of hostnames
107 XXX and just add a new reference to a hostname that
108 XXX already exists, if possible, rather than creating
109 XXX a new structure. */
110 if (!dns_host_entry_allocate (dh
, name
, MDL
)) {
111 log_error ("Can't allocate space for new host.");
117 int make_const_data (expr
, data
, len
, terminated
, allocate
)
118 struct expression
**expr
;
119 const unsigned char *data
;
124 struct expression
*nt
;
126 if (!expression_allocate (expr
, MDL
)) {
127 log_error ("No memory for make_const_data tree node.");
134 if (!buffer_allocate (&nt
-> data
.const_data
.buffer
,
135 len
+ terminated
, MDL
)) {
136 log_error ("Can't allocate const_data buffer");
137 expression_dereference (expr
, MDL
);
140 nt
-> data
.const_data
.data
=
141 &nt
-> data
.const_data
.buffer
-> data
[0];
142 memcpy (nt
-> data
.const_data
.buffer
-> data
,
143 data
, len
+ terminated
);
145 nt
-> data
.const_data
.data
= data
;
146 nt
-> data
.const_data
.terminated
= terminated
;
148 nt
-> data
.const_data
.data
= 0;
150 nt
-> op
= expr_const_data
;
151 nt
-> data
.const_data
.len
= len
;
155 int make_const_int (expr
, val
)
156 struct expression
**expr
;
159 if (!expression_allocate (expr
, MDL
)) {
160 log_error ("No memory for make_const_data tree node.");
164 (*expr
) -> op
= expr_const_int
;
165 (*expr
) -> data
.const_int
= val
;
169 int make_concat (expr
, left
, right
)
170 struct expression
**expr
;
171 struct expression
*left
, *right
;
173 /* If we're concatenating a null tree to a non-null tree, just
174 return the non-null tree; if both trees are null, return
179 expression_reference (expr
, right
, MDL
);
183 expression_reference (expr
, left
, MDL
);
187 /* Otherwise, allocate a new node to concatenate the two. */
188 if (!expression_allocate (expr
, MDL
)) {
189 log_error ("No memory for concatenation expression node.");
193 (*expr
) -> op
= expr_concat
;
194 expression_reference (&(*expr
) -> data
.concat
[0], left
, MDL
);
195 expression_reference (&(*expr
) -> data
.concat
[1], right
, MDL
);
199 int make_encapsulation (expr
, name
)
200 struct expression
**expr
;
201 struct data_string
*name
;
203 /* Allocate a new node to store the encapsulation. */
204 if (!expression_allocate (expr
, MDL
)) {
205 log_error ("No memory for encapsulation expression node.");
209 (*expr
) -> op
= expr_encapsulate
;
210 data_string_copy (&(*expr
) -> data
.encapsulate
, name
, MDL
);
214 int make_substring (new, expr
, offset
, length
)
215 struct expression
**new;
216 struct expression
*expr
;
217 struct expression
*offset
;
218 struct expression
*length
;
220 /* Allocate an expression node to compute the substring. */
221 if (!expression_allocate (new, MDL
)) {
222 log_error ("no memory for substring expression.");
225 (*new) -> op
= expr_substring
;
226 expression_reference (&(*new) -> data
.substring
.expr
, expr
, MDL
);
227 expression_reference (&(*new) -> data
.substring
.offset
, offset
, MDL
);
228 expression_reference (&(*new) -> data
.substring
.len
, length
, MDL
);
232 int make_limit (new, expr
, limit
)
233 struct expression
**new;
234 struct expression
*expr
;
237 struct expression
*rv
;
239 /* Allocate a node to enforce a limit on evaluation. */
240 if (!expression_allocate (new, MDL
))
241 log_error ("no memory for limit expression");
242 (*new) -> op
= expr_substring
;
243 expression_reference (&(*new) -> data
.substring
.expr
, expr
, MDL
);
245 /* Offset is a constant 0. */
246 if (!expression_allocate (&(*new) -> data
.substring
.offset
, MDL
)) {
247 log_error ("no memory for limit offset expression");
248 expression_dereference (new, MDL
);
251 (*new) -> data
.substring
.offset
-> op
= expr_const_int
;
252 (*new) -> data
.substring
.offset
-> data
.const_int
= 0;
254 /* Length is a constant: the specified limit. */
255 if (!expression_allocate (&(*new) -> data
.substring
.len
, MDL
)) {
256 log_error ("no memory for limit length expression");
257 expression_dereference (new, MDL
);
260 (*new) -> data
.substring
.len
-> op
= expr_const_int
;
261 (*new) -> data
.substring
.len
-> data
.const_int
= limit
;
266 int option_cache (oc
, dp
, expr
, option
)
267 struct option_cache
**oc
;
268 struct data_string
*dp
;
269 struct expression
*expr
;
270 struct option
*option
;
272 if (!option_cache_allocate (oc
, MDL
))
275 data_string_copy (&(*oc
) -> data
, dp
, MDL
);
277 expression_reference (&(*oc
) -> expression
, expr
, MDL
);
278 (*oc
) -> option
= option
;
282 int make_let (result
, name
)
283 struct executable_statement
**result
;
286 if (!(executable_statement_allocate (result
, MDL
)))
289 (*result
) -> op
= let_statement
;
290 (*result
) -> data
.let
.name
= dmalloc (strlen (name
) + 1, MDL
);
291 if (!(*result
) -> data
.let
.name
) {
292 executable_statement_dereference (result
, MDL
);
295 strcpy ((*result
) -> data
.let
.name
, name
);
299 static int do_host_lookup (result
, dns
)
300 struct data_string
*result
;
301 struct dns_host_entry
*dns
;
308 log_debug ("time: now = %d dns = %d diff = %d",
309 cur_time
, dns
-> timeout
, cur_time
- dns
-> timeout
);
312 /* If the record hasn't timed out, just copy the data and return. */
313 if (cur_time
<= dns
-> timeout
) {
315 log_debug ("easy copy: %d %s",
318 ? inet_ntoa (*(struct in_addr
*)(dns
-> data
.data
))
321 data_string_copy (result
, &dns
-> data
, MDL
);
325 log_debug ("Looking up %s", dns
-> hostname
);
328 /* Otherwise, look it up... */
329 h
= gethostbyname (dns
-> hostname
);
335 log_error ("%s: host unknown.", dns
-> hostname
);
339 log_error ("%s: temporary name server failure",
343 log_error ("%s: name server failed", dns
-> hostname
);
346 log_error ("%s: no A record associated with address",
349 #endif /* !NO_H_ERRNO */
351 /* Okay to try again after a minute. */
352 dns
-> timeout
= cur_time
+ 60;
353 data_string_forget (&dns
-> data
, MDL
);
358 log_debug ("Lookup succeeded; first address is %s",
359 inet_ntoa (h
-> h_addr_list
[0]));
362 /* Count the number of addresses we got... */
363 for (count
= 0; h
-> h_addr_list
[count
]; count
++)
366 /* Dereference the old data, if any. */
367 data_string_forget (&dns
-> data
, MDL
);
369 /* Do we need to allocate more memory? */
370 new_len
= count
* h
-> h_length
;
371 if (!buffer_allocate (&dns
-> data
.buffer
, new_len
, MDL
))
373 log_error ("No memory for %s.", dns
-> hostname
);
377 dns
-> data
.data
= &dns
-> data
.buffer
-> data
[0];
378 dns
-> data
.len
= new_len
;
379 dns
-> data
.terminated
= 0;
381 /* Addresses are conveniently stored one to the buffer, so we
382 have to copy them out one at a time... :'( */
383 for (i
= 0; i
< count
; i
++) {
384 memcpy (&dns
-> data
.buffer
-> data
[h
-> h_length
* i
],
385 h
-> h_addr_list
[i
], (unsigned)(h
-> h_length
));
388 log_debug ("dns -> data: %x h -> h_addr_list [0]: %x",
389 *(int *)(dns
-> buffer
), h
-> h_addr_list
[0]);
392 /* XXX Set the timeout for an hour from now.
393 XXX This should really use the time on the DNS reply. */
394 dns
-> timeout
= cur_time
+ 3600;
397 log_debug ("hard copy: %d %s", dns
-> data
.len
,
399 ? inet_ntoa (*(struct in_addr
*)(dns
-> data
.data
)) : 0));
401 data_string_copy (result
, &dns
-> data
, MDL
);
405 #if defined (NSUPDATE)
406 int evaluate_dns_expression (result
, packet
, lease
, in_options
,
407 cfg_options
, scope
, expr
)
409 struct packet
*packet
;
411 struct option_state
*in_options
;
412 struct option_state
*cfg_options
;
413 struct binding_scope
*scope
;
414 struct expression
*expr
;
417 unsigned long ttl
= 0;
419 struct data_string name
, data
;
422 if (!result
|| *result
) {
423 log_error ("evaluate_dns_expression called with non-null %s",
425 #if defined (POINTER_DEBUG)
432 switch (expr
-> op
) {
433 #if defined (NSUPDATE)
435 r0
= evaluate_numeric_expression (&ttl
, packet
, lease
,
436 in_options
, cfg_options
,
438 expr
-> data
.ns_add
.ttl
);
445 case expr_ns_not_exists
:
448 memset (&name
, 0, sizeof name
);
449 r1
= evaluate_data_expression (&name
, packet
, lease
,
450 in_options
, cfg_options
, scope
,
451 expr
-> data
.ns_add
.rrname
);
453 /* The result of the evaluation may or may not
454 be NUL-terminated, but we need it
455 terminated for sure, so we have to allocate
456 a buffer and terminate it. */
457 tname
= dmalloc (name
.len
+ 1, MDL
);
461 data_string_forget (&name
, MDL
);
463 memcpy (tname
, name
.data
, name
.len
);
464 tname
[name
.len
] = 0;
465 memset (&data
, 0, sizeof data
);
466 r2
= evaluate_data_expression
467 (&data
, packet
, lease
, in_options
,
469 expr
-> data
.ns_add
.rrdata
);
473 if (r0
&& r1
&& (r2
|| expr
-> op
!= expr_ns_add
)) {
474 *result
= res_mkupdrec (((expr
-> op
== expr_ns_add
||
475 expr
-> op
== expr_ns_delete
)
476 ? S_UPDATE
: S_PREREQ
),
477 tname
, expr
-> data
.ns_add
.rrclass
,
478 expr
-> data
.ns_add
.rrtype
, ttl
);
482 data_string_forget (&data
, MDL
);
487 /* As a special case, if we get exactly
488 four bytes of data, it's an IP address
489 represented as a 32-bit quantity, which
490 is actually what we *should* be getting
491 here. Because res_mkupdrec is currently
492 broken and expects a dotted quad, convert
493 it. This should be fixed when the new
494 resolver is merged. */
496 (*result
) -> r_data
= dmalloc (16, MDL
);
497 if (!(*result
) -> r_data
)
499 sprintf ((*result
) -> r_data
,
501 data
.data
[0], data
.data
[1],
502 data
.data
[2], data
.data
[3]);
503 (*result
) -> r_size
=
504 strlen ((*result
) -> r_data
);
506 (*result
) -> r_size
= data
.len
;
507 (*result
) -> r_data
= dmalloc (data
.len
,
509 if (!(*result
) -> r_data
) {
510 dpngood
: /* double plus ungood. */
511 res_freeupdrec (*result
);
515 memcpy ((*result
) -> r_data
,
516 data
.data
, data
.len
);
519 (*result
) -> r_data
= 0;
520 (*result
) -> r_size
= 0;
522 switch (expr
-> op
) {
524 (*result
) -> r_opcode
= ADD
;
527 (*result
) -> r_opcode
= DELETE
;
530 (*result
) -> r_opcode
= YXRRSET
;
532 case expr_ns_not_exists
:
533 (*result
) -> r_opcode
= NXRRSET
;
536 /* Can't happen, but satisfy gcc. */
543 data_string_forget (&name
, MDL
);
547 data_string_forget (&data
, MDL
);
548 /* One flaw in the thinking here: an IP address and an
549 ASCII string both look like data expressions, but
550 for A records, we want an ASCII string, not a
551 binary IP address. Do I need to turn binary IP
552 addresses into a seperate type? */
554 (r2
|| expr
-> op
!= expr_ns_add
) && *result
);
560 case expr_ns_not_exists
:
573 case expr_variable_exists
:
574 log_error ("Boolean opcode in evaluate_dns_expression: %d",
583 case expr_const_data
:
586 case expr_encapsulate
:
587 case expr_host_lookup
:
588 case expr_encode_int8
:
589 case expr_encode_int16
:
590 case expr_encode_int32
:
591 case expr_binary_to_ascii
:
595 case expr_pick_first_value
:
596 case expr_host_decl_name
:
597 case expr_config_option
:
598 case expr_leased_address
:
600 case expr_variable_reference
:
601 log_error ("Data opcode in evaluate_dns_expression: %d",
605 case expr_extract_int8
:
606 case expr_extract_int16
:
607 case expr_extract_int32
:
609 case expr_lease_time
:
610 case expr_dns_transaction
:
611 log_error ("Numeric opcode in evaluate_dns_expression: %d",
616 log_error ("Bogus opcode in evaluate_dns_expression: %d",
620 #endif /* defined (NSUPDATE) */
622 int evaluate_boolean_expression (result
, packet
, lease
, in_options
,
623 cfg_options
, scope
, expr
)
625 struct packet
*packet
;
627 struct option_state
*in_options
;
628 struct option_state
*cfg_options
;
629 struct binding_scope
*scope
;
630 struct expression
*expr
;
632 struct data_string left
, right
;
633 struct data_string rrtype
, rrname
, rrdata
;
635 int srrtype
, srrname
, srrdata
, sttl
;
638 struct binding
*binding
;
640 switch (expr
-> op
) {
642 *result
= check_collection (packet
, lease
,
644 #if defined (DEBUG_EXPRESSIONS)
645 log_debug ("bool: check (%s) returns %s",
646 expr
-> data
.check
-> name
, *result
? "true" : "false");
652 memset (&left
, 0, sizeof left
);
653 sleft
= evaluate_data_expression (&left
, packet
, lease
,
654 in_options
, cfg_options
,
656 expr
-> data
.equal
[0]);
657 memset (&right
, 0, sizeof right
);
658 sright
= evaluate_data_expression (&right
, packet
, lease
,
659 in_options
, cfg_options
,
661 expr
-> data
.equal
[1]);
662 if (sleft
&& sright
) {
663 if (left
.len
== right
.len
&&
664 !memcmp (left
.data
, right
.data
, left
.len
))
665 *result
= expr
-> op
== expr_equal
;
667 *result
= expr
-> op
== expr_not_equal
;
670 #if defined (DEBUG_EXPRESSIONS)
671 log_debug ("bool: %sequal (%s, %s) = %s",
672 expr
-> op
== expr_not_equal
? "not" : "",
674 ? print_hex_1 (left
.len
, left
.data
, 30)
677 ? print_hex_2 (right
.len
, right
.data
, 30)
680 ? (*result
? "true" : "false")
684 data_string_forget (&left
, MDL
);
686 data_string_forget (&right
, MDL
);
687 return sleft
&& sright
;
690 sleft
= evaluate_boolean_expression (&bleft
, packet
, lease
,
691 in_options
, cfg_options
,
693 expr
-> data
.and [0]);
694 sright
= evaluate_boolean_expression (&bright
, packet
, lease
,
695 in_options
, cfg_options
,
697 expr
-> data
.and [1]);
699 #if defined (DEBUG_EXPRESSIONS)
700 log_debug ("bool: and (%s, %s) = %s",
701 sleft
? (bleft
? "true" : "false") : "NULL",
702 sright
? (bright
? "true" : "false") : "NULL",
704 ? (bleft
&& bright
? "true" : "false") : "NULL"));
706 if (sleft
&& sright
) {
707 *result
= bleft
&& bright
;
713 sleft
= evaluate_boolean_expression (&bleft
, packet
, lease
,
714 in_options
, cfg_options
,
716 expr
-> data
.or [0]);
717 sright
= evaluate_boolean_expression (&bright
, packet
, lease
,
718 in_options
, cfg_options
,
720 expr
-> data
.or [1]);
721 #if defined (DEBUG_EXPRESSIONS)
722 log_debug ("bool: or (%s, %s) = %s",
723 sleft
? (bleft
? "true" : "false") : "NULL",
724 sright
? (bright
? "true" : "false") : "NULL",
726 ? (bleft
|| bright
? "true" : "false") : "NULL"));
728 if (sleft
&& sright
) {
729 *result
= bleft
|| bright
;
735 sleft
= evaluate_boolean_expression (&bleft
, packet
, lease
,
736 in_options
, cfg_options
,
739 #if defined (DEBUG_EXPRESSIONS)
740 log_debug ("bool: not (%s) = %s",
741 sleft
? (bleft
? "true" : "false") : "NULL",
743 ? (!bleft
? "true" : "false") : "NULL"));
753 memset (&left
, 0, sizeof left
);
755 !((*expr
-> data
.option
-> universe
-> get_func
)
756 (&left
, expr
-> data
.exists
-> universe
,
757 packet
, lease
, in_options
, cfg_options
, in_options
,
758 scope
, expr
-> data
.exists
-> code
)))
762 data_string_forget (&left
, MDL
);
764 #if defined (DEBUG_EXPRESSIONS)
765 log_debug ("bool: exists %s.%s = %s",
766 expr
-> data
.option
-> universe
-> name
,
767 expr
-> data
.option
-> name
,
768 *result
? "true" : MDL
);
774 #if defined (DEBUG_EXPRESSIONS)
775 log_debug ("bool: known = NULL");
779 #if defined (DEBUG_EXPRESSIONS)
780 log_debug ("bool: known = %s",
781 packet
-> known
? "true" : "false");
783 *result
= packet
-> known
;
787 if (!lease
|| !(lease
-> flags
& STATIC_LEASE
)) {
788 #if defined (DEBUG_EXPRESSIONS)
789 log_debug ("bool: static = false");
794 #if defined (DEBUG_EXPRESSIONS)
795 log_debug ("bool: static = true");
800 case expr_variable_exists
:
801 binding
= find_binding (scope
, expr
-> data
.variable
);
804 if (binding
-> value
.data
)
810 #if defined (DEBUG_EXPRESSIONS)
811 log_debug ("boolean: %s? = %s", expr
-> variable
,
812 s0
? "true" : "false");
822 case expr_const_data
:
825 case expr_encapsulate
:
826 case expr_host_lookup
:
827 case expr_encode_int8
:
828 case expr_encode_int16
:
829 case expr_encode_int32
:
830 case expr_binary_to_ascii
:
832 case expr_pick_first_value
:
833 case expr_host_decl_name
:
834 case expr_config_option
:
835 case expr_leased_address
:
837 case expr_variable_reference
:
840 log_error ("Data opcode in evaluate_boolean_expression: %d",
844 case expr_extract_int8
:
845 case expr_extract_int16
:
846 case expr_extract_int32
:
848 case expr_lease_time
:
849 case expr_dns_transaction
:
850 log_error ("Numeric opcode in evaluate_boolean_expression: %d",
857 case expr_ns_not_exists
:
858 log_error ("dns opcode in evaluate_boolean_expression: %d",
863 log_error ("Bogus opcode in evaluate_boolean_expression: %d",
868 int evaluate_data_expression (result
, packet
, lease
,
869 in_options
, cfg_options
, scope
, expr
)
870 struct data_string
*result
;
871 struct packet
*packet
;
873 struct option_state
*in_options
;
874 struct option_state
*cfg_options
;
875 struct binding_scope
*scope
;
876 struct expression
*expr
;
878 struct data_string data
, other
;
879 unsigned long offset
, len
, i
;
882 struct binding
*binding
;
885 switch (expr
-> op
) {
886 /* Extract N bytes starting at byte M of a data string. */
888 memset (&data
, 0, sizeof data
);
889 s0
= evaluate_data_expression (&data
, packet
, lease
,
890 in_options
, cfg_options
, scope
,
891 expr
-> data
.substring
.expr
);
893 /* Evaluate the offset and length. */
894 s1
= evaluate_numeric_expression
895 (&offset
, packet
, lease
, in_options
, cfg_options
,
896 scope
, expr
-> data
.substring
.offset
);
897 s2
= evaluate_numeric_expression (&len
, packet
, lease
,
898 in_options
, cfg_options
,
900 expr
-> data
.substring
.len
);
902 if (s0
&& s1
&& s2
) {
903 /* If the offset is after end of the string,
904 return an empty string. Otherwise, do the
905 adjustments and return what's left. */
906 if (data
.len
> offset
) {
907 data_string_copy (result
, &data
, MDL
);
908 result
-> len
-= offset
;
909 if (result
-> len
> len
) {
911 result
-> terminated
= 0;
913 result
-> data
+= offset
;
919 #if defined (DEBUG_EXPRESSIONS)
920 log_debug ("data: substring (%s, %s, %s) = %s",
921 s0
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
922 s1
? print_dec_1 (offset
) : "NULL",
923 s2
? print_dec_2 (len
) : "NULL",
924 (s3
? print_hex_2 (result
-> len
, result
-> data
, 30)
928 data_string_forget (&data
, MDL
);
934 /* Extract the last N bytes of a data string. */
936 memset (&data
, 0, sizeof data
);
937 s0
= evaluate_data_expression (&data
, packet
, lease
,
938 in_options
, cfg_options
, scope
,
939 expr
-> data
.suffix
.expr
);
940 /* Evaluate the length. */
941 s1
= evaluate_numeric_expression (&len
, packet
, lease
,
942 in_options
, cfg_options
,
944 expr
-> data
.substring
.len
);
946 data_string_copy (result
, &data
, MDL
);
948 /* If we are returning the last N bytes of a
949 string whose length is <= N, just return
950 the string - otherwise, compute a new
951 starting address and decrease the
953 if (data
.len
> len
) {
954 result
-> data
+= data
.len
- len
;
959 #if defined (DEBUG_EXPRESSIONS)
960 log_debug ("data: suffix (%s, %s) = %s",
961 s0
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
962 s1
? print_dec_1 (len
) : "NULL",
964 ? print_hex_2 (result
-> len
, result
-> data
, 30)
969 /* Extract an option. */
972 s0
= ((*expr
-> data
.option
-> universe
-> get_func
)
973 (result
, expr
-> data
.option
-> universe
,
975 in_options
, cfg_options
, in_options
,
976 scope
, expr
-> data
.option
-> code
));
980 #if defined (DEBUG_EXPRESSIONS)
981 log_debug ("data: option %s.%s = %s",
982 expr
-> data
.option
-> universe
-> name
,
983 expr
-> data
.option
-> name
,
984 s0
? print_hex_1 (result
-> len
, result
-> data
, 60)
989 case expr_config_option
:
991 s0
= ((*expr
-> data
.option
-> universe
-> get_func
)
992 (result
, expr
-> data
.option
-> universe
,
994 in_options
, cfg_options
, cfg_options
,
995 scope
, expr
-> data
.option
-> code
));
999 #if defined (DEBUG_EXPRESSIONS)
1000 log_debug ("data: config-option %s.%s = %s",
1001 expr
-> data
.option
-> universe
-> name
,
1002 expr
-> data
.option
-> name
,
1003 s0
? print_hex_1 (result
-> len
, result
-> data
, 60)
1008 /* Combine the hardware type and address. */
1010 if (!packet
|| !packet
-> raw
) {
1011 log_error ("data: hardware: raw packet not available");
1014 if (packet
-> raw
-> hlen
> sizeof packet
-> raw
-> chaddr
) {
1015 log_error ("data: hardware: invalid hlen (%d)\n",
1016 packet
-> raw
-> hlen
);
1019 result
-> len
= packet
-> raw
-> hlen
+ 1;
1020 if (buffer_allocate (&result
-> buffer
, result
-> len
, MDL
)) {
1021 result
-> data
= &result
-> buffer
-> data
[0];
1022 result
-> buffer
-> data
[0] = packet
-> raw
-> htype
;
1023 memcpy (&result
-> buffer
-> data
[1],
1024 packet
-> raw
-> chaddr
,
1025 packet
-> raw
-> hlen
);
1026 result
-> terminated
= 0;
1028 log_error ("data: hardware: no memory for buffer.");
1031 #if defined (DEBUG_EXPRESSIONS)
1032 log_debug ("data: hardware = %s",
1033 print_hex_1 (result
-> len
, result
-> data
, 60));
1037 /* Extract part of the raw packet. */
1039 if (!packet
|| !packet
-> raw
) {
1040 log_error ("data: packet: raw packet not available");
1044 s0
= evaluate_numeric_expression (&offset
, packet
, lease
,
1045 in_options
, cfg_options
,
1047 expr
-> data
.packet
.offset
);
1048 s1
= evaluate_numeric_expression (&len
,
1050 in_options
, cfg_options
,
1052 expr
-> data
.packet
.len
);
1053 if (s0
&& s1
&& offset
< packet
-> packet_length
) {
1054 if (offset
+ len
> packet
-> packet_length
)
1056 packet
-> packet_length
- offset
;
1058 result
-> len
= len
;
1059 if (buffer_allocate (&result
-> buffer
,
1060 result
-> len
, MDL
)) {
1061 result
-> data
= &result
-> buffer
-> data
[0];
1062 memcpy (result
-> buffer
-> data
,
1063 (((unsigned char *)(packet
-> raw
))
1064 + offset
), result
-> len
);
1065 result
-> terminated
= 0;
1067 log_error ("data: packet: no buffer memory.");
1073 #if defined (DEBUG_EXPRESSIONS)
1074 log_debug ("data: packet (%ld, %ld) = %s",
1076 s2
? print_hex_1 (result
-> len
,
1077 result
-> data
, 60) : NULL
);
1081 /* The encapsulation of all defined options in an
1083 case expr_encapsulate
:
1085 s0
= option_space_encapsulate
1086 (result
, packet
, lease
,
1087 in_options
, cfg_options
, scope
,
1088 &expr
-> data
.encapsulate
);
1092 #if defined (DEBUG_EXPRESSIONS)
1093 log_debug ("data: encapsulate (%s) = %s",
1094 expr
-> data
.encapsulate
.data
,
1095 s0
? print_hex_1 (result
-> len
,
1096 result
-> data
, 60) : "NULL");
1100 /* Some constant data... */
1101 case expr_const_data
:
1102 #if defined (DEBUG_EXPRESSIONS)
1103 log_debug ("data: const = %s",
1104 print_hex_1 (expr
-> data
.const_data
.len
,
1105 expr
-> data
.const_data
.data
, 60));
1107 data_string_copy (result
,
1108 &expr
-> data
.const_data
, MDL
);
1111 /* Hostname lookup... */
1112 case expr_host_lookup
:
1113 s0
= do_host_lookup (result
, expr
-> data
.host_lookup
);
1114 #if defined (DEBUG_EXPRESSIONS)
1115 log_debug ("data: DNS lookup (%s) = %s",
1116 expr
-> data
.host_lookup
-> hostname
,
1118 ? print_dotted_quads (result
-> len
, result
-> data
)
1123 /* Concatenation... */
1125 memset (&data
, 0, sizeof data
);
1126 s0
= evaluate_data_expression (&data
, packet
, lease
,
1127 in_options
, cfg_options
, scope
,
1128 expr
-> data
.concat
[0]);
1129 memset (&other
, 0, sizeof other
);
1130 s1
= evaluate_data_expression (&other
, packet
, lease
,
1131 in_options
, cfg_options
, scope
,
1132 expr
-> data
.concat
[1]);
1135 result
-> len
= data
.len
+ other
.len
;
1136 if (!buffer_allocate (&result
-> buffer
,
1138 other
.terminated
), MDL
)) {
1139 log_error ("data: concat: no memory");
1141 data_string_forget (&data
, MDL
);
1142 data_string_forget (&other
, MDL
);
1145 result
-> data
= &result
-> buffer
-> data
[0];
1146 memcpy (result
-> buffer
-> data
, data
.data
, data
.len
);
1147 memcpy (&result
-> buffer
-> data
[data
.len
],
1148 other
.data
, other
.len
+ other
.terminated
);
1150 data_string_forget (&data
, MDL
);
1152 data_string_forget (&other
, MDL
);
1153 #if defined (DEBUG_EXPRESSIONS)
1154 log_debug ("data: concat (%s, %s) = %s",
1155 s0
? print_hex_1 (data
.len
, data
.data
, 20) : "NULL",
1156 s1
? print_hex_2 (other
.len
, other
.data
, 20) : "NULL",
1158 ? print_hex_3 (result
-> len
, result
-> data
, 30)
1163 case expr_encode_int8
:
1164 s0
= evaluate_numeric_expression (&len
, packet
, lease
,
1165 in_options
, cfg_options
,
1167 expr
-> data
.packet
.len
);
1170 if (!buffer_allocate (&result
-> buffer
, 1, MDL
)) {
1171 log_error ("data: encode_int8: no memory");
1175 result
-> data
= &result
-> buffer
-> data
[0];
1176 result
-> buffer
-> data
[0] = len
;
1181 #if defined (DEBUG_EXPRESSIONS)
1183 log_debug ("data: encode_int8 (NULL) = NULL");
1185 log_debug ("data: encode_int8 (%ld) = %s", len
,
1186 print_hex_2 (result
-> len
,
1187 result
-> data
, 20));
1192 case expr_encode_int16
:
1193 s0
= evaluate_numeric_expression (&len
, packet
, lease
,
1194 in_options
, cfg_options
,
1196 expr
-> data
.packet
.len
);
1199 if (!buffer_allocate (&result
-> buffer
, 2, MDL
)) {
1200 log_error ("data: encode_int16: no memory");
1204 result
-> data
= &result
-> buffer
-> data
[0];
1205 putUShort (result
-> buffer
-> data
, len
);
1210 #if defined (DEBUG_EXPRESSIONS)
1212 log_debug ("data: encode_int16 (NULL) = NULL");
1214 log_debug ("data: encode_int16 (%ld) = %s", len
,
1215 print_hex_2 (result
-> len
,
1216 result
-> data
, 20));
1220 case expr_encode_int32
:
1221 s0
= evaluate_numeric_expression (&len
, packet
, lease
,
1222 in_options
, cfg_options
,
1224 expr
-> data
.packet
.len
);
1227 if (!buffer_allocate (&result
-> buffer
, 4, MDL
)) {
1228 log_error ("data: encode_int32: no memory");
1232 result
-> data
= &result
-> buffer
-> data
[0];
1233 putULong (result
-> buffer
-> data
, len
);
1238 #if defined (DEBUG_EXPRESSIONS)
1240 log_debug ("data: encode_int32 (NULL) = NULL");
1242 log_debug ("data: encode_int32 (%ld) = %s", len
,
1243 print_hex_2 (result
-> len
,
1244 result
-> data
, 20));
1248 case expr_binary_to_ascii
:
1249 /* Evaluate the base (offset) and width (len): */
1250 s0
= evaluate_numeric_expression
1251 (&offset
, packet
, lease
, in_options
, cfg_options
,
1252 scope
, expr
-> data
.b2a
.base
);
1253 s1
= evaluate_numeric_expression (&len
, packet
, lease
,
1254 in_options
, cfg_options
,
1256 expr
-> data
.b2a
.width
);
1258 /* Evaluate the seperator string. */
1259 memset (&data
, 0, sizeof data
);
1260 s2
= evaluate_data_expression (&data
, packet
, lease
,
1261 in_options
, cfg_options
, scope
,
1262 expr
-> data
.b2a
.seperator
);
1264 /* Evaluate the data to be converted. */
1265 memset (&other
, 0, sizeof other
);
1266 s3
= evaluate_data_expression (&other
, packet
, lease
,
1267 in_options
, cfg_options
, scope
,
1268 expr
-> data
.b2a
.buffer
);
1270 if (s0
&& s1
&& s2
&& s3
) {
1273 if (len
!= 8 && len
!= 16 && len
!= 32) {
1274 log_info ("binary_to_ascii: %s %ld!",
1275 "invalid width", len
);
1280 /* The buffer must be a multiple of the number's
1282 if (other
.len
% len
) {
1283 log_info ("binary-to-ascii: %s %d %s %ld!",
1284 "length of buffer", other
.len
,
1285 "not a multiple of width", len
);
1290 /* Count the width of the output. */
1292 for (i
= 0; i
< other
.len
; i
+= len
) {
1295 if (other
.data
[i
] < 8)
1297 else if (other
.data
[i
] < 64)
1301 } else if (offset
== 10) {
1302 if (other
.data
[i
] < 10)
1304 else if (other
.data
[i
] < 100)
1308 } else if (offset
== 10) {
1309 if (other
.data
[i
] < 16)
1314 buflen
+= (converted_length
1318 buflen
+= (converted_length
1321 if (i
+ len
!= other
.len
)
1325 if (!buffer_allocate (&result
-> buffer
,
1327 log_error ("data: binary-to-ascii: no memory");
1331 result
-> data
= &result
-> buffer
-> data
[0];
1332 result
-> len
= buflen
;
1333 result
-> terminated
= 1;
1336 for (i
= 0; i
< other
.len
; i
+= len
) {
1337 buflen
+= (binary_to_ascii
1338 (&result
-> buffer
-> data
[buflen
],
1339 &other
.data
[i
], offset
, len
));
1340 if (i
+ len
!= other
.len
) {
1342 buffer
-> data
[buflen
],
1343 data
.data
, data
.len
);
1347 /* NUL terminate. */
1348 result
-> buffer
-> data
[buflen
] = 0;
1354 #if defined (DEBUG_EXPRESSIONS)
1355 log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s",
1356 s0
? print_dec_1 (offset
) : "NULL",
1357 s1
? print_dec_2 (len
) : "NULL",
1358 s2
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
1359 s3
? print_hex_2 (other
.len
, other
.data
, 30) : "NULL",
1360 (status
? print_hex_3 (result
-> len
, result
-> data
, 30)
1364 data_string_forget (&data
, MDL
);
1366 data_string_forget (&other
, MDL
);
1372 /* Evaluate the width (len): */
1373 s0
= evaluate_numeric_expression
1374 (&len
, packet
, lease
, in_options
, cfg_options
,
1375 scope
, expr
-> data
.reverse
.width
);
1377 /* Evaluate the data. */
1378 memset (&data
, 0, sizeof data
);
1379 s1
= evaluate_data_expression (&data
, packet
, lease
,
1380 in_options
, cfg_options
, scope
,
1381 expr
-> data
.reverse
.buffer
);
1387 /* The buffer must be a multiple of the number's
1389 if (other
.len
% len
) {
1390 log_info ("reverse: %s %d %s %ld!",
1391 "length of buffer", other
.len
,
1392 "not a multiple of width", len
);
1397 /* XXX reverse in place? I don't think we can. */
1398 if (!buffer_allocate (&result
-> buffer
,
1400 log_error ("data: reverse: no memory");
1404 result
-> data
= &result
-> buffer
-> data
[0];
1405 result
-> len
= data
.len
;
1406 result
-> terminated
= 0;
1408 for (i
= 0; i
< data
.len
; i
+= len
) {
1409 memcpy (&result
-> buffer
-> data
[i
],
1410 &data
.data
[data
.len
- i
- len
], len
);
1417 #if defined (DEBUG_EXPRESSIONS)
1418 log_debug ("data: reverse (%s, %s) = %s",
1419 s0
? print_dec_1 (len
) : "NULL",
1420 s1
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
1421 (status
? print_hex_3 (result
-> len
, result
-> data
, 30)
1425 data_string_forget (&data
, MDL
);
1430 case expr_leased_address
:
1432 log_error ("data: leased_address: not available");
1435 result
-> len
= lease
-> ip_addr
.len
;
1436 if (buffer_allocate (&result
-> buffer
, result
-> len
, MDL
)) {
1437 result
-> data
= &result
-> buffer
-> data
[0];
1438 memcpy (&result
-> buffer
-> data
[0],
1439 lease
-> ip_addr
.iabuf
, lease
-> ip_addr
.len
);
1440 result
-> terminated
= 0;
1442 log_error ("data: leased-address: no memory.");
1445 #if defined (DEBUG_EXPRESSIONS)
1446 log_debug ("data: leased-address = %s",
1447 print_hex_1 (result
-> len
, result
-> data
, 60));
1451 case expr_pick_first_value
:
1452 memset (&data
, 0, sizeof data
);
1453 if ((evaluate_data_expression
1454 (result
, packet
, lease
, in_options
, cfg_options
, scope
,
1455 expr
-> data
.pick_first_value
.car
))) {
1456 #if defined (DEBUG_EXPRESSIONS)
1457 log_debug ("data: pick_first_value (%s, ???)",
1458 print_hex_1 (result
-> len
,
1459 result
-> data
, 40));
1464 if (expr
-> data
.pick_first_value
.cdr
&&
1465 (evaluate_data_expression
1466 (result
, packet
, lease
, in_options
, cfg_options
, scope
,
1467 expr
-> data
.pick_first_value
.cdr
))) {
1468 #if defined (DEBUG_EXPRESSIONS)
1469 log_debug ("data: pick_first_value (NULL, %s)",
1470 print_hex_1 (result
-> len
,
1471 result
-> data
, 40));
1476 #if defined (DEBUG_EXPRESSIONS)
1477 log_debug ("data: pick_first_value (NULL, NULL) = NULL");
1481 case expr_host_decl_name
:
1482 if (!lease
|| !lease
-> host
) {
1483 log_error ("data: host_decl_name: not available");
1486 result
-> len
= strlen (lease
-> host
-> name
);
1487 if (buffer_allocate (&result
-> buffer
,
1488 result
-> len
+ 1, MDL
)) {
1489 result
-> data
= &result
-> buffer
-> data
[0];
1490 strcpy ((char *)&result
-> buffer
-> data
[0],
1491 lease
-> host
-> name
);
1492 result
-> terminated
= 1;
1494 log_error ("data: host-decl-name: no memory.");
1497 #if defined (DEBUG_EXPRESSIONS)
1498 log_debug ("data: host-decl-name = %s", lease
-> host
-> name
);
1503 #if defined (DEBUG_EXPRESSIONS)
1504 log_debug ("data: null = NULL");
1508 case expr_variable_reference
:
1509 binding
= find_binding (scope
, expr
-> data
.variable
);
1512 if (binding
-> value
.data
) {
1513 data_string_copy (result
,
1514 &binding
-> value
, MDL
);
1520 #if defined (DEBUG_EXPRESSIONS)
1521 log_debug ("data: %s = %s", expr
-> variable
,
1522 s0
? print_hex_1 (result
-> len
,
1523 result
-> data
, 50);
1527 /* Extract the filename. */
1529 if (packet
&& packet
-> raw
-> file
[0]) {
1531 memchr (packet
-> raw
-> file
, 0,
1532 sizeof packet
-> raw
-> file
);
1534 fn
= ((char *)packet
-> raw
-> file
+
1535 sizeof packet
-> raw
-> file
);
1536 result
-> len
= fn
- &(packet
-> raw
-> file
[0]);
1537 if (buffer_allocate (&result
-> buffer
,
1538 result
-> len
+ 1, MDL
)) {
1539 result
-> data
= &result
-> buffer
-> data
[0];
1540 memcpy (&result
-> buffer
-> data
[0],
1541 packet
-> raw
-> file
,
1543 result
-> buffer
-> data
[result
-> len
] = 0;
1544 result
-> terminated
= 1;
1547 log_error ("data: filename: no memory.");
1553 #if defined (DEBUG_EXPRESSIONS)
1554 log_info ("data: filename = \"%s\"",
1555 s0
? result
-> data
: "NULL");
1559 /* Extract the server name. */
1561 if (packet
&& packet
-> raw
-> sname
[0]) {
1563 memchr (packet
-> raw
-> sname
, 0,
1564 sizeof packet
-> raw
-> sname
);
1566 fn
= ((char *)packet
-> raw
-> sname
+
1567 sizeof packet
-> raw
-> sname
);
1568 result
-> len
= fn
- &packet
-> raw
-> sname
[0];
1569 if (buffer_allocate (&result
-> buffer
,
1570 result
-> len
+ 1, MDL
)) {
1571 result
-> data
= &result
-> buffer
-> data
[0];
1572 memcpy (&result
-> buffer
-> data
[0],
1573 packet
-> raw
-> sname
,
1575 result
-> buffer
-> data
[result
-> len
] = 0;
1576 result
-> terminated
= 1;
1579 log_error ("data: sname: no memory.");
1585 #if defined (DEBUG_EXPRESSIONS)
1586 log_info ("data: sname = \"%s\"",
1587 s0
? result
-> data
: "NULL");
1593 case expr_not_equal
:
1602 case expr_variable_exists
:
1603 log_error ("Boolean opcode in evaluate_data_expression: %d",
1607 case expr_extract_int8
:
1608 case expr_extract_int16
:
1609 case expr_extract_int32
:
1610 case expr_const_int
:
1611 case expr_lease_time
:
1612 case expr_dns_transaction
:
1613 log_error ("Numeric opcode in evaluate_data_expression: %d",
1618 case expr_ns_delete
:
1619 case expr_ns_exists
:
1620 case expr_ns_not_exists
:
1621 log_error ("dns update opcode in evaluate_data_expression: %d",
1626 log_error ("Bogus opcode in evaluate_data_expression: %d", expr
-> op
);
1630 int evaluate_numeric_expression (result
, packet
, lease
,
1631 in_options
, cfg_options
, scope
, expr
)
1632 unsigned long *result
;
1633 struct packet
*packet
;
1634 struct lease
*lease
;
1635 struct option_state
*in_options
;
1636 struct option_state
*cfg_options
;
1637 struct binding_scope
*scope
;
1638 struct expression
*expr
;
1640 struct data_string data
;
1642 #if defined (NSUPDATE)
1644 static struct __res_state res
;
1648 struct expression
*cur
, *next
;
1650 switch (expr
-> op
) {
1653 case expr_not_equal
:
1662 case expr_variable_exists
:
1663 log_error ("Boolean opcode in evaluate_numeric_expression: %d",
1667 case expr_substring
:
1671 case expr_const_data
:
1674 case expr_encapsulate
:
1675 case expr_host_lookup
:
1676 case expr_encode_int8
:
1677 case expr_encode_int16
:
1678 case expr_encode_int32
:
1679 case expr_binary_to_ascii
:
1683 case expr_pick_first_value
:
1684 case expr_host_decl_name
:
1685 case expr_config_option
:
1686 case expr_leased_address
:
1688 case expr_variable_reference
:
1689 log_error ("Data opcode in evaluate_numeric_expression: %d",
1693 case expr_extract_int8
:
1694 memset (&data
, 0, sizeof data
);
1695 status
= evaluate_data_expression
1696 (&data
, packet
, lease
, in_options
, cfg_options
,
1697 scope
, expr
-> data
.extract_int
);
1699 *result
= data
.data
[0];
1700 #if defined (DEBUG_EXPRESSIONS)
1701 log_debug ("num: extract_int8 (%s) = %s",
1702 status
? print_hex_1 (data
.len
, data
.data
, 60) : "NULL",
1703 status
? print_dec_1 (*result
) : "NULL" );
1705 if (status
) data_string_forget (&data
, MDL
);
1708 case expr_extract_int16
:
1709 memset (&data
, 0, sizeof data
);
1710 status
= (evaluate_data_expression
1711 (&data
, packet
, lease
, in_options
, cfg_options
,
1712 scope
, expr
-> data
.extract_int
));
1713 if (status
&& data
.len
>= 2)
1714 *result
= getUShort (data
.data
);
1715 #if defined (DEBUG_EXPRESSIONS)
1716 log_debug ("num: extract_int16 (%s) = %ld",
1717 ((status
&& data
.len
>= 2) ?
1718 print_hex_1 (data
.len
, data
.data
, 60) : "NULL"),
1721 if (status
) data_string_forget (&data
, MDL
);
1722 return (status
&& data
.len
>= 2);
1724 case expr_extract_int32
:
1725 memset (&data
, 0, sizeof data
);
1726 status
= (evaluate_data_expression
1727 (&data
, packet
, lease
, in_options
, cfg_options
,
1728 scope
, expr
-> data
.extract_int
));
1729 if (status
&& data
.len
>= 4)
1730 *result
= getULong (data
.data
);
1731 #if defined (DEBUG_EXPRESSIONS)
1732 log_debug ("num: extract_int32 (%s) = %ld",
1733 ((status
&& data
.len
>= 4) ?
1734 print_hex_1 (data
.len
, data
.data
, 60) : "NULL"),
1737 if (status
) data_string_forget (&data
, MDL
);
1738 return (status
&& data
.len
>= 4);
1740 case expr_const_int
:
1741 *result
= expr
-> data
.const_int
;
1742 #if defined (DEBUG_EXPRESSIONS)
1743 log_debug ("number: CONSTANT = %ld", *result
);
1747 case expr_lease_time
:
1749 log_error ("data: leased_lease: not available");
1752 if (lease
-> ends
< cur_time
) {
1753 log_error ("%s %lu when it is now %lu",
1754 "data: lease_time: lease ends at",
1755 lease
-> ends
, cur_time
);
1758 *result
= lease
-> ends
- cur_time
;
1759 #if defined (DEBUG_EXPRESSIONS)
1760 log_debug ("number: lease-time = (%lu - %lu) = %ld",
1766 case expr_dns_transaction
:
1767 #if !defined (NSUPDATE)
1777 next
= cur
-> data
.dns_transaction
.cdr
;
1779 status
= (evaluate_dns_expression
1780 (&nut
, packet
, lease
, in_options
, cfg_options
,
1781 scope
, cur
-> data
.dns_transaction
.car
));
1784 APPEND (uq
, nut
, r_link
);
1788 /* Do the update and record the error code, if there was
1789 an error; otherwise set it to NOERROR. */
1790 if (res_nupdate (&res
, HEAD (uq
), NULL
))
1793 /* The resolver doesn't return any actual error
1794 codes - just 1 for success, zero for failure! */
1795 /* *result = res.res_h_errno; */
1799 print_dns_status ((int)*result
, &uq
);
1802 while (!EMPTY (uq
)) {
1803 ns_updrec
*tmp
= HEAD (uq
);
1804 UNLINK (uq
, tmp
, r_link
);
1805 if (tmp
-> r_data
) {
1806 dfree (tmp
-> r_data
, MDL
);
1807 tmp
-> r_data
= (char *)0;
1809 if (tmp
-> r_dname
) {
1810 dfree (tmp
-> r_dname
, MDL
);
1811 tmp
-> r_dname
= (char *)0;
1813 res_freeupdrec (tmp
);
1816 #endif /* NSUPDATE */
1819 case expr_ns_delete
:
1820 case expr_ns_exists
:
1821 case expr_ns_not_exists
:
1822 log_error ("dns opcode in evaluate_numeric_expression: %d",
1827 log_error ("evaluate_numeric_expression: bogus opcode %d", expr
-> op
);
1831 /* Return data hanging off of an option cache structure, or if there
1832 isn't any, evaluate the expression hanging off of it and return the
1833 result of that evaluation. There should never be both an expression
1834 and a valid data_string. */
1836 int evaluate_option_cache (result
, packet
, lease
,
1837 in_options
, cfg_options
, scope
, oc
, file
, line
)
1838 struct data_string
*result
;
1839 struct packet
*packet
;
1840 struct lease
*lease
;
1841 struct option_state
*in_options
;
1842 struct option_state
*cfg_options
;
1843 struct binding_scope
*scope
;
1844 struct option_cache
*oc
;
1848 if (oc
-> data
.len
) {
1849 data_string_copy (result
, &oc
-> data
, file
, line
);
1852 if (!oc
-> expression
)
1854 return evaluate_data_expression (result
, packet
, lease
,
1855 in_options
, cfg_options
, scope
,
1859 /* Evaluate an option cache and extract a boolean from the result,
1860 returning the boolean. Return false if there is no data. */
1862 int evaluate_boolean_option_cache (ignorep
, packet
, lease
, in_options
,
1863 cfg_options
, scope
, oc
, file
, line
)
1865 struct packet
*packet
;
1866 struct lease
*lease
;
1867 struct option_state
*in_options
;
1868 struct option_state
*cfg_options
;
1869 struct binding_scope
*scope
;
1870 struct option_cache
*oc
;
1874 struct data_string ds
;
1877 /* So that we can be called with option_lookup as an argument. */
1878 if (!oc
|| !in_options
)
1881 memset (&ds
, 0, sizeof ds
);
1882 if (!evaluate_option_cache (&ds
, packet
, lease
, in_options
,
1883 cfg_options
, scope
, oc
, file
, line
))
1887 result
= ds
.data
[0];
1894 result
= 0; data_string_forget (&ds
, MDL
);
1899 /* Evaluate a boolean expression and return the result of the evaluation,
1900 or FALSE if it failed. */
1902 int evaluate_boolean_expression_result (ignorep
, packet
, lease
, in_options
,
1903 cfg_options
, scope
, expr
)
1905 struct packet
*packet
;
1906 struct lease
*lease
;
1907 struct option_state
*in_options
;
1908 struct option_state
*cfg_options
;
1909 struct binding_scope
*scope
;
1910 struct expression
*expr
;
1914 /* So that we can be called with option_lookup as an argument. */
1918 if (!evaluate_boolean_expression (&result
, packet
, lease
,
1919 in_options
, cfg_options
,
1932 /* Dereference an expression node, and if the reference count goes to zero,
1933 dereference any data it refers to, and then free it. */
1934 void expression_dereference (eptr
, file
, line
)
1935 struct expression
**eptr
;
1939 struct expression
*expr
= *eptr
;
1941 /* Zero the pointer. */
1942 *eptr
= (struct expression
*)0;
1944 /* Decrement the reference count. If it's nonzero, we're
1947 rc_register (file
, line
, expr
, expr
-> refcnt
);
1948 if (expr
-> refcnt
> 0)
1950 if (expr
-> refcnt
< 0) {
1951 log_error ("%s(%d): negative refcnt!", file
, line
);
1952 #if defined (DEBUG_RC_HISTORY)
1955 #if defined (POINTER_DEBUG)
1962 /* Dereference subexpressions. */
1963 switch (expr
-> op
) {
1964 /* All the binary operators can be handled the same way. */
1966 case expr_not_equal
:
1970 if (expr
-> data
.equal
[0])
1971 expression_dereference (&expr
-> data
.equal
[0],
1973 if (expr
-> data
.equal
[1])
1974 expression_dereference (&expr
-> data
.equal
[1],
1978 case expr_substring
:
1979 if (expr
-> data
.substring
.expr
)
1980 expression_dereference (&expr
-> data
.substring
.expr
,
1982 if (expr
-> data
.substring
.offset
)
1983 expression_dereference (&expr
-> data
.substring
.offset
,
1985 if (expr
-> data
.substring
.len
)
1986 expression_dereference (&expr
-> data
.substring
.len
,
1991 if (expr
-> data
.suffix
.expr
)
1992 expression_dereference (&expr
-> data
.suffix
.expr
,
1994 if (expr
-> data
.suffix
.len
)
1995 expression_dereference (&expr
-> data
.suffix
.len
,
2000 if (expr
-> data
.not)
2001 expression_dereference (&expr
-> data
.not, file
, line
);
2005 if (expr
-> data
.packet
.offset
)
2006 expression_dereference (&expr
-> data
.packet
.offset
,
2008 if (expr
-> data
.packet
.len
)
2009 expression_dereference (&expr
-> data
.packet
.len
,
2013 case expr_extract_int8
:
2014 case expr_extract_int16
:
2015 case expr_extract_int32
:
2016 if (expr
-> data
.extract_int
)
2017 expression_dereference (&expr
-> data
.extract_int
,
2021 case expr_encode_int8
:
2022 case expr_encode_int16
:
2023 case expr_encode_int32
:
2024 if (expr
-> data
.encode_int
)
2025 expression_dereference (&expr
-> data
.encode_int
,
2029 case expr_encapsulate
:
2030 case expr_const_data
:
2031 data_string_forget (&expr
-> data
.const_data
, file
, line
);
2034 case expr_host_lookup
:
2035 if (expr
-> data
.host_lookup
)
2036 dns_host_entry_dereference (&expr
-> data
.host_lookup
,
2040 case expr_binary_to_ascii
:
2041 if (expr
-> data
.b2a
.base
)
2042 expression_dereference (&expr
-> data
.b2a
.base
,
2044 if (expr
-> data
.b2a
.width
)
2045 expression_dereference (&expr
-> data
.b2a
.width
,
2047 if (expr
-> data
.b2a
.seperator
)
2048 expression_dereference (&expr
-> data
.b2a
.seperator
,
2050 if (expr
-> data
.b2a
.buffer
)
2051 expression_dereference (&expr
-> data
.b2a
.buffer
,
2055 case expr_pick_first_value
:
2056 if (expr
-> data
.pick_first_value
.car
)
2057 expression_dereference (&expr
-> data
.pick_first_value
.car
,
2059 if (expr
-> data
.pick_first_value
.cdr
)
2060 expression_dereference (&expr
-> data
.pick_first_value
.cdr
,
2065 if (expr
-> data
.reverse
.width
)
2066 expression_dereference (&expr
-> data
.reverse
.width
,
2068 if (expr
-> data
.reverse
.buffer
)
2069 expression_dereference
2070 (&expr
-> data
.reverse
.buffer
, file
, line
);
2073 case expr_dns_transaction
:
2074 if (expr
-> data
.dns_transaction
.car
)
2075 expression_dereference (&expr
-> data
.dns_transaction
.car
,
2077 if (expr
-> data
.dns_transaction
.cdr
)
2078 expression_dereference (&expr
-> data
.dns_transaction
.cdr
,
2083 if (expr
-> data
.ns_add
.rrname
)
2084 expression_dereference (&expr
-> data
.ns_add
.rrname
,
2086 if (expr
-> data
.ns_add
.rrdata
)
2087 expression_dereference (&expr
-> data
.ns_add
.rrdata
,
2089 if (expr
-> data
.ns_add
.ttl
)
2090 expression_dereference (&expr
-> data
.ns_add
.ttl
,
2094 case expr_ns_delete
:
2095 case expr_ns_exists
:
2096 case expr_ns_not_exists
:
2097 if (expr
-> data
.ns_delete
.rrname
)
2098 expression_dereference (&expr
-> data
.ns_delete
.rrname
,
2100 if (expr
-> data
.ns_delete
.rrdata
)
2101 expression_dereference (&expr
-> data
.ns_delete
.rrdata
,
2105 case expr_variable_reference
:
2106 case expr_variable_exists
:
2107 if (expr
-> data
.variable
)
2108 dfree (expr
-> data
.variable
, file
, line
);
2111 /* No subexpressions. */
2112 case expr_leased_address
:
2113 case expr_lease_time
:
2116 case expr_const_int
:
2128 free_expression (expr
, MDL
);
2131 int is_dns_expression (expr
)
2132 struct expression
*expr
;
2134 return (expr
-> op
== expr_ns_add
||
2135 expr
-> op
== expr_ns_delete
||
2136 expr
-> op
== expr_ns_exists
||
2137 expr
-> op
== expr_ns_not_exists
);
2140 int is_boolean_expression (expr
)
2141 struct expression
*expr
;
2143 return (expr
-> op
== expr_check
||
2144 expr
-> op
== expr_exists
||
2145 expr
-> op
== expr_variable_exists
||
2146 expr
-> op
== expr_equal
||
2147 expr
-> op
== expr_not_equal
||
2148 expr
-> op
== expr_and
||
2149 expr
-> op
== expr_or
||
2150 expr
-> op
== expr_not
||
2151 expr
-> op
== expr_known
||
2152 expr
-> op
== expr_static
);
2155 int is_data_expression (expr
)
2156 struct expression
*expr
;
2158 return (expr
-> op
== expr_substring
||
2159 expr
-> op
== expr_suffix
||
2160 expr
-> op
== expr_option
||
2161 expr
-> op
== expr_hardware
||
2162 expr
-> op
== expr_const_data
||
2163 expr
-> op
== expr_packet
||
2164 expr
-> op
== expr_concat
||
2165 expr
-> op
== expr_encapsulate
||
2166 expr
-> op
== expr_encode_int8
||
2167 expr
-> op
== expr_encode_int16
||
2168 expr
-> op
== expr_encode_int32
||
2169 expr
-> op
== expr_host_lookup
||
2170 expr
-> op
== expr_binary_to_ascii
||
2171 expr
-> op
== expr_filename
||
2172 expr
-> op
== expr_sname
||
2173 expr
-> op
== expr_reverse
||
2174 expr
-> op
== expr_pick_first_value
||
2175 expr
-> op
== expr_host_decl_name
||
2176 expr
-> op
== expr_leased_address
||
2177 expr
-> op
== expr_config_option
||
2178 expr
-> op
== expr_null
||
2179 expr
-> op
== expr_variable_reference
);
2182 int is_numeric_expression (expr
)
2183 struct expression
*expr
;
2185 return (expr
-> op
== expr_extract_int8
||
2186 expr
-> op
== expr_extract_int16
||
2187 expr
-> op
== expr_extract_int32
||
2188 expr
-> op
== expr_const_int
||
2189 expr
-> op
== expr_lease_time
||
2190 expr
-> op
== expr_dns_transaction
);
2193 int is_compound_expression (expr
)
2194 struct expression
*expr
;
2196 return (expr
-> op
== expr_ns_add
||
2197 expr
-> op
== expr_ns_delete
||
2198 expr
-> op
== expr_ns_exists
||
2199 expr
-> op
== expr_ns_not_exists
||
2200 expr
-> op
== expr_substring
||
2201 expr
-> op
== expr_suffix
||
2202 expr
-> op
== expr_option
||
2203 expr
-> op
== expr_concat
||
2204 expr
-> op
== expr_encode_int8
||
2205 expr
-> op
== expr_encode_int16
||
2206 expr
-> op
== expr_encode_int32
||
2207 expr
-> op
== expr_binary_to_ascii
||
2208 expr
-> op
== expr_reverse
||
2209 expr
-> op
== expr_pick_first_value
||
2210 expr
-> op
== expr_config_option
||
2211 expr
-> op
== expr_extract_int8
||
2212 expr
-> op
== expr_extract_int16
||
2213 expr
-> op
== expr_extract_int32
||
2214 expr
-> op
== expr_dns_transaction
);
2217 static int op_val
PROTO ((enum expr_op
));
2219 static int op_val (op
)
2227 case expr_substring
:
2230 case expr_encapsulate
:
2231 case expr_host_lookup
:
2236 case expr_const_data
:
2237 case expr_extract_int8
:
2238 case expr_extract_int16
:
2239 case expr_extract_int32
:
2240 case expr_encode_int8
:
2241 case expr_encode_int16
:
2242 case expr_encode_int32
:
2243 case expr_const_int
:
2245 case expr_variable_exists
:
2247 case expr_binary_to_ascii
:
2251 case expr_pick_first_value
:
2252 case expr_host_decl_name
:
2253 case expr_config_option
:
2254 case expr_leased_address
:
2255 case expr_lease_time
:
2256 case expr_dns_transaction
:
2258 case expr_variable_reference
:
2260 case expr_ns_delete
:
2261 case expr_ns_exists
:
2262 case expr_ns_not_exists
:
2266 case expr_not_equal
:
2278 int op_precedence (op1
, op2
)
2279 enum expr_op op1
, op2
;
2283 return op_val (op1
) - op_val (op2
);
2286 enum expression_context
op_context (op
)
2290 /* XXX Why aren't these specific? */
2295 case expr_substring
:
2298 case expr_encapsulate
:
2299 case expr_host_lookup
:
2304 case expr_const_data
:
2305 case expr_extract_int8
:
2306 case expr_extract_int16
:
2307 case expr_extract_int32
:
2308 case expr_encode_int8
:
2309 case expr_encode_int16
:
2310 case expr_encode_int32
:
2311 case expr_const_int
:
2313 case expr_variable_exists
:
2315 case expr_binary_to_ascii
:
2319 case expr_pick_first_value
:
2320 case expr_host_decl_name
:
2321 case expr_config_option
:
2322 case expr_leased_address
:
2323 case expr_lease_time
:
2325 case expr_variable_reference
:
2327 case expr_ns_delete
:
2328 case expr_ns_exists
:
2329 case expr_ns_not_exists
:
2330 case expr_dns_transaction
:
2334 case expr_not_equal
:
2335 return context_data
;
2338 return context_boolean
;
2341 return context_boolean
;
2346 int write_expression (file
, expr
, col
, indent
, firstp
)
2348 struct expression
*expr
;
2353 struct expression
*e
;
2359 /* If this promises to be a fat expression, start a new line. */
2360 if (!firstp
&& is_compound_expression (expr
)) {
2361 indent_spaces (file
, indent
);
2365 switch (expr
-> op
) {
2367 col
= token_print_indent (file
, col
, indent
, "", "", "null");
2371 col
= token_print_indent (file
, col
, indent
, "", "", "check");
2372 col
= token_print_indent_concat (file
, col
, indent
,
2374 expr
-> data
.check
-> name
,
2378 case expr_not_equal
:
2385 col
= write_expression (file
, expr
-> data
.equal
[0],
2387 col
= token_print_indent (file
, col
, indent
, " ", " ", s
);
2388 col
= write_expression (file
, expr
-> data
.equal
[1],
2389 col
, indent
+ 2, 0);
2392 case expr_substring
:
2393 col
= token_print_indent (file
, col
, indent
, "", "",
2395 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
2397 col
= write_expression (file
, expr
-> data
.substring
.expr
,
2399 col
= token_print_indent (file
, col
, indent
, "", " ", ",");
2400 col
= write_expression (file
, expr
-> data
.substring
.offset
,
2402 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
2403 col
= write_expression (file
, expr
-> data
.substring
.len
,
2405 col
= token_print_indent (file
, col
, indent
, "", "", ")");
2409 col
= token_print_indent (file
, col
, indent
, "", "", "suffix");
2410 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
2412 col
= write_expression (file
, expr
-> data
.suffix
.expr
,
2414 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
2415 col
= write_expression (file
, expr
-> data
.suffix
.len
,
2417 col
= token_print_indent (file
, col
, indent
, "", "", ")");
2422 col
= token_print_indent (file
, col
, indent
, "", "",
2424 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
2428 col
= write_expression (file
, e
-> data
.concat
[0],
2431 if (!e
-> data
.concat
[1])
2433 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
2434 if (e
-> data
.concat
[1] -> op
== expr_concat
) {
2435 e
= e
-> data
.concat
[1];
2438 col
= write_expression (file
, e
-> data
.concat
[1],
2441 col
= token_print_indent (file
, col
, indent
, "", "", ")");
2444 case expr_host_lookup
:
2445 col
= token_print_indent (file
, col
, indent
, "", "",
2447 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
2448 col
= token_print_indent_concat
2449 (file
, col
, indent
, "", "",
2450 "\"", expr
-> data
.host_lookup
-> hostname
, "\"",
2452 col
= token_print_indent (file
, col
, indent
, "", "", ")");
2464 col
= token_print_indent (file
, col
, indent
, "", " ", "not");
2465 col
= write_expression (file
,
2466 expr
-> data
.not, col
, indent
+ 2, 1);
2473 col
= token_print_indent (file
, col
, indent
, "", "", s
);
2475 if (expr
-> data
.option
-> universe
!= &dhcp_universe
) {
2476 col
= token_print_indent (file
, col
, indent
,
2478 (expr
-> data
.option
->
2480 col
= token_print_indent (file
, col
, indent
, "", "",
2482 col
= token_print_indent (file
, col
, indent
, "", "",
2483 expr
-> data
.option
-> name
);
2485 col
= token_print_indent (file
, col
, indent
, " ", "",
2486 expr
-> data
.option
-> name
);
2491 col
= token_print_indent (file
, col
, indent
, "", "",
2496 col
= token_print_indent (file
, col
, indent
, "", "",
2498 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
2500 col
= write_expression (file
, expr
-> data
.packet
.offset
,
2502 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
2503 col
= write_expression (file
, expr
-> data
.packet
.len
,
2505 col
= token_print_indent (file
, col
, indent
, "", "", ")");
2508 case expr_const_data
:
2509 col
= token_indent_data_string (file
, col
, indent
, "", "",
2510 &expr
-> data
.const_data
);
2513 case expr_extract_int8
:
2516 col
= token_print_indent (file
, col
, indent
, "", "",
2518 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
2520 col
= write_expression (file
, expr
-> data
.extract_int
,
2522 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
2523 sprintf (obuf
, "%d", width
);
2524 col
= token_print_indent (file
, col
, scol
, " ", "", obuf
);
2525 col
= token_print_indent (file
, col
, indent
, "", "", ")");
2528 case expr_extract_int16
:
2532 case expr_extract_int32
:
2536 case expr_encode_int8
:
2539 col
= token_print_indent (file
, col
, indent
, "", "",
2541 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
2543 col
= write_expression (file
, expr
-> data
.extract_int
,
2545 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
2546 sprintf (obuf
, "%d", width
);
2547 col
= token_print_indent (file
, col
, scol
, " ", "", obuf
);
2548 col
= token_print_indent (file
, col
, indent
, "", "",
2552 case expr_encode_int16
:
2556 case expr_encode_int32
:
2560 case expr_const_int
:
2561 sprintf (obuf
, "%lu", expr
-> data
.const_int
);
2562 col
= token_print_indent (file
, col
, indent
, "", "", obuf
);
2567 goto print_option_name
;
2569 case expr_encapsulate
:
2570 col
= token_print_indent (file
, col
, indent
, "", "",
2572 col
= token_indent_data_string (file
, col
, indent
, " ", "",
2573 &expr
-> data
.encapsulate
);
2577 col
= token_print_indent (file
, col
, indent
, "", "", "known");
2581 col
= token_print_indent (file
, col
, indent
, "", "",
2583 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
2585 col
= write_expression (file
, expr
-> data
.reverse
.width
,
2587 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
2588 col
= write_expression (file
, expr
-> data
.reverse
.buffer
,
2590 col
= token_print_indent (file
, col
, indent
, "", "",
2594 case expr_leased_address
:
2595 col
= token_print_indent (file
, col
, indent
, "", "",
2599 case expr_binary_to_ascii
:
2600 col
= token_print_indent (file
, col
, indent
, "", "",
2602 col
= token_print_indent (file
, col
, indent
, " ", "",
2605 col
= write_expression (file
, expr
-> data
.b2a
.base
,
2607 col
= token_print_indent (file
, col
, scol
, "", " ",
2609 col
= write_expression (file
, expr
-> data
.b2a
.width
,
2611 col
= token_print_indent (file
, col
, scol
, "", " ",
2613 col
= write_expression (file
, expr
-> data
.b2a
.seperator
,
2615 col
= token_print_indent (file
, col
, scol
, "", " ",
2617 col
= write_expression (file
, expr
-> data
.b2a
.buffer
,
2619 col
= token_print_indent (file
, col
, indent
, "", "",
2623 case expr_config_option
:
2624 s
= "config-option";
2625 goto print_option_name
;
2627 case expr_host_decl_name
:
2628 col
= token_print_indent (file
, col
, indent
, "", "",
2632 case expr_pick_first_value
:
2634 col
= token_print_indent (file
, col
, indent
, "", "",
2636 col
= token_print_indent (file
, col
, indent
, " ", "",
2641 col
= write_expression (file
,
2642 e
-> data
.pick_first_value
.car
,
2645 /* We're being very lisp-like right now - instead of
2646 representing this expression as (first middle . last) we're
2647 representing it as (first middle last), which means that the
2648 tail cdr is always nil. Apologies to non-wisp-lizards - may
2649 this obscure way of describing the problem motivate you to
2650 learn more about the one true computing language. */
2651 if (!e
-> data
.pick_first_value
.cdr
)
2653 col
= token_print_indent (file
, col
, scol
, "", " ",
2655 if (e
-> data
.pick_first_value
.cdr
-> op
==
2656 expr_pick_first_value
) {
2657 e
= e
-> data
.pick_first_value
.cdr
;
2660 col
= write_expression (file
,
2661 e
-> data
.pick_first_value
.cdr
,
2664 col
= token_print_indent (file
, col
, indent
, "", "",
2668 case expr_lease_time
:
2669 col
= token_print_indent (file
, col
, indent
, "", "",
2673 case expr_dns_transaction
:
2674 col
= token_print_indent (file
, col
, indent
, "", "",
2676 col
= token_print_indent (file
, col
, indent
, " ", "",
2680 e
&& e
-> op
== expr_dns_transaction
;
2681 e
= e
-> data
.dns_transaction
.cdr
) {
2687 col
= write_expression (file
,
2688 e
-> data
.dns_transaction
.car
,
2690 if (e
-> data
.dns_transaction
.cdr
)
2691 col
= token_print_indent (file
, col
, scol
,
2695 col
= write_expression (file
, e
, col
, scol
, 0);
2696 col
= token_print_indent (file
, col
, indent
, "", "", ")");
2700 col
= token_print_indent (file
, col
, indent
, "", "",
2702 col
= token_print_indent (file
, col
, indent
, " ", "",
2705 sprintf (obuf
, "%d", expr
-> data
.ns_add
.rrclass
);
2706 col
= token_print_indent (file
, col
, scol
, "", "", obuf
);
2707 col
= token_print_indent (file
, col
, scol
, "", " ",
2709 sprintf (obuf
, "%d", expr
-> data
.ns_add
.rrtype
);
2710 col
= token_print_indent (file
, col
, scol
, "", "", obuf
);
2711 col
= token_print_indent (file
, col
, scol
, "", " ",
2713 col
= write_expression (file
, expr
-> data
.ns_add
.rrname
,
2715 col
= token_print_indent (file
, col
, scol
, "", " ",
2717 col
= write_expression (file
, expr
-> data
.ns_add
.rrdata
,
2719 col
= token_print_indent (file
, col
, scol
, "", " ",
2721 col
= write_expression (file
, expr
-> data
.ns_add
.ttl
,
2723 col
= token_print_indent (file
, col
, indent
, "", "",
2727 case expr_ns_delete
:
2728 col
= token_print_indent (file
, col
, indent
, "", "",
2730 col
= token_print_indent (file
, col
, indent
, " ", "",
2734 sprintf (obuf
, "%d", expr
-> data
.ns_add
.rrclass
);
2735 col
= token_print_indent (file
, col
, scol
, "", "", obuf
);
2736 col
= token_print_indent (file
, col
, scol
, "", " ",
2738 sprintf (obuf
, "%d", expr
-> data
.ns_add
.rrtype
);
2739 col
= token_print_indent (file
, col
, scol
, "", "", obuf
);
2740 col
= token_print_indent (file
, col
, scol
, "", " ",
2742 col
= write_expression (file
, expr
-> data
.ns_add
.rrname
,
2744 col
= token_print_indent (file
, col
, scol
, "", " ",
2746 col
= write_expression (file
, expr
-> data
.ns_add
.rrdata
,
2748 col
= token_print_indent (file
, col
, indent
, "", "",
2752 case expr_ns_exists
:
2753 col
= token_print_indent (file
, col
, indent
, "", "",
2755 col
= token_print_indent (file
, col
, indent
, " ", "",
2757 goto finish_ns_small
;
2759 case expr_ns_not_exists
:
2760 col
= token_print_indent (file
, col
, indent
, "", "",
2762 col
= token_print_indent (file
, col
, indent
, " ", "",
2764 goto finish_ns_small
;
2767 col
= token_print_indent (file
, col
, indent
, "", "",
2772 col
= token_print_indent (file
, col
, indent
, "", "", "null");
2775 case expr_variable_reference
:
2776 col
= token_print_indent (file
, indent
, indent
, "", "",
2777 expr
-> data
.variable
);
2780 case expr_variable_exists
:
2781 col
= token_print_indent (file
, indent
, indent
, "", "",
2783 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
2784 col
= token_print_indent (file
, col
, indent
, "", "",
2785 expr
-> data
.variable
);
2786 col
= token_print_indent (file
, col
, indent
, "", "", ")");
2790 log_fatal ("invalid expression type in print_expression: %d",
2796 struct binding
*find_binding (struct binding_scope
*scope
, const char *name
)
2799 struct binding_scope
*s
;
2801 for (s
= scope
; s
; s
= s
-> outer
) {
2802 for (bp
= s
-> bindings
; bp
; bp
= bp
-> next
) {
2803 if (!strcasecmp (name
, bp
-> name
)) {
2808 return (struct binding
*)0;
2811 int free_bindings (struct binding_scope
*scope
, const char *file
, int line
)
2813 struct binding
*bp
, *next
;
2815 for (bp
= scope
-> bindings
; bp
; bp
= next
) {
2818 dfree (bp
-> name
, file
, line
);
2819 if (bp
-> value
.data
)
2820 data_string_forget (&bp
-> value
, file
, line
);
2821 dfree (bp
, file
, line
);
2823 scope
-> bindings
= (struct binding
*)0;
2827 int binding_scope_dereference (ptr
, file
, line
)
2828 struct binding_scope
**ptr
;
2832 struct binding_scope
*bp
;
2834 if (!ptr
|| !*ptr
) {
2835 log_error ("%s(%d): null pointer", file
, line
);
2836 #if defined (POINTER_DEBUG)
2843 if ((*ptr
) -> bindings
)
2844 free_bindings (*ptr
, file
, line
);
2845 dfree ((*ptr
), file
, line
);
2846 *ptr
= (struct binding_scope
*)0;
2850 /* vim: set tabstop=8: */