tools/adflib: build only host variant which is used by Sam440 target
[AROS.git] / workbench / network / stacks / AROSTCP / dhcp / common / execute.c
blob2684eba9a6d35d0a4b76a112ed5f76bd7ef8b5ed
1 /* execute.c
3 Support for executable statements. */
5 /*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1998-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
35 #if 0
36 static char copyright[] =
37 "$Id$ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
38 #endif
40 #include "dhcpd.h"
41 #include <omapip/omapip_p.h>
43 int execute_statements (result, packet, lease, client_state,
44 in_options, out_options, scope, statements)
45 struct binding_value **result;
46 struct packet *packet;
47 struct lease *lease;
48 struct client_state *client_state;
49 struct option_state *in_options;
50 struct option_state *out_options;
51 struct binding_scope **scope;
52 struct executable_statement *statements;
54 struct executable_statement *r, *e, *next;
55 int rc;
56 int status;
57 // unsigned long num;
58 __unused struct binding_scope *outer;
59 struct binding *binding;
60 struct data_string ds;
61 struct binding_scope *ns;
63 if (!statements)
64 return 1;
66 r = (struct executable_statement *)0;
67 next = (struct executable_statement *)0;
68 e = (struct executable_statement *)0;
69 executable_statement_reference (&r, statements, MDL);
70 while (r && !(result && *result)) {
71 if (r -> next)
72 executable_statement_reference (&next, r -> next, MDL);
73 switch (r -> op) {
74 case statements_statement:
75 #if defined (DEBUG_EXPRESSIONS)
76 log_debug ("exec: statements");
77 #endif
78 status = execute_statements (result, packet, lease,
79 client_state, in_options,
80 out_options, scope,
81 r -> data.statements);
82 #if defined (DEBUG_EXPRESSIONS)
83 log_debug ("exec: statements returns %d", status);
84 #endif
85 if (!status)
86 return 0;
87 break;
89 case on_statement:
90 if (lease) {
91 if (r -> data.on.evtypes & ON_EXPIRY) {
92 #if defined (DEBUG_EXPRESSIONS)
93 log_debug ("exec: on expiry");
94 #endif
95 if (lease -> on_expiry)
96 executable_statement_dereference
97 (&lease -> on_expiry, MDL);
98 if (r -> data.on.statements)
99 executable_statement_reference
100 (&lease -> on_expiry,
101 r -> data.on.statements, MDL);
103 if (r -> data.on.evtypes & ON_RELEASE) {
104 #if defined (DEBUG_EXPRESSIONS)
105 log_debug ("exec: on release");
106 #endif
107 if (lease -> on_release)
108 executable_statement_dereference
109 (&lease -> on_release, MDL);
110 if (r -> data.on.statements)
111 executable_statement_reference
112 (&lease -> on_release,
113 r -> data.on.statements, MDL);
115 if (r -> data.on.evtypes & ON_COMMIT) {
116 #if defined (DEBUG_EXPRESSIONS)
117 log_debug ("exec: on commit");
118 #endif
119 if (lease -> on_commit)
120 executable_statement_dereference
121 (&lease -> on_commit, MDL);
122 if (r -> data.on.statements)
123 executable_statement_reference
124 (&lease -> on_commit,
125 r -> data.on.statements, MDL);
128 break;
130 case switch_statement:
131 #if defined (DEBUG_EXPRESSIONS)
132 log_debug ("exec: switch");
133 #endif
134 status = (find_matching_case
135 (&e, packet, lease, client_state,
136 in_options, out_options, scope,
137 r -> data.s_switch.expr,
138 r -> data.s_switch.statements));
139 #if defined (DEBUG_EXPRESSIONS)
140 log_debug ("exec: switch: case %lx", (unsigned long)e);
141 #endif
142 if (status) {
143 if (!(execute_statements
144 (result, packet, lease, client_state,
145 in_options, out_options, scope, e))) {
146 executable_statement_dereference
147 (&e, MDL);
148 return 0;
150 executable_statement_dereference (&e, MDL);
152 break;
154 /* These have no effect when executed. */
155 case case_statement:
156 case default_statement:
157 break;
159 case if_statement:
160 status = (evaluate_boolean_expression
161 (&rc, packet,
162 lease, client_state, in_options,
163 out_options, scope, r -> data.ie.expr));
165 #if defined (DEBUG_EXPRESSIONS)
166 log_debug ("exec: if %s", (status
167 ? (rc ? "true" : "false")
168 : "NULL"));
169 #endif
170 /* XXX Treat NULL as false */
171 if (!status)
172 rc = 0;
173 if (!execute_statements
174 (result, packet, lease, client_state,
175 in_options, out_options, scope,
176 rc ? r -> data.ie.tc : r -> data.ie.fc))
177 return 0;
178 break;
180 case eval_statement:
181 status = evaluate_expression
182 ((struct binding_value **)0,
183 packet, lease, client_state, in_options,
184 out_options, scope, r -> data.eval, MDL);
185 #if defined (DEBUG_EXPRESSIONS)
186 log_debug ("exec: evaluate: %s",
187 (status ? "succeeded" : "failed"));
188 #endif
189 break;
191 case return_statement:
192 status = evaluate_expression
193 (result, packet,
194 lease, client_state, in_options,
195 out_options, scope, r -> data.retval, MDL);
196 #if defined (DEBUG_EXPRESSIONS)
197 log_debug ("exec: return: %s",
198 (status ? "succeeded" : "failed"));
199 #endif
200 break;
202 case add_statement:
203 #if defined (DEBUG_EXPRESSIONS)
204 log_debug ("exec: add %s", (r -> data.add -> name
205 ? r -> data.add -> name
206 : "<unnamed class>"));
207 #endif
208 classify (packet, r -> data.add);
209 break;
211 case break_statement:
212 #if defined (DEBUG_EXPRESSIONS)
213 log_debug ("exec: break");
214 #endif
215 return 1;
217 case supersede_option_statement:
218 case send_option_statement:
219 #if defined (DEBUG_EXPRESSIONS)
220 log_debug ("exec: %s option %s.%s",
221 (r -> op == supersede_option_statement
222 ? "supersede" : "send"),
223 r -> data.option -> option -> universe -> name,
224 r -> data.option -> option -> name);
225 goto option_statement;
226 #endif
227 case default_option_statement:
228 #if defined (DEBUG_EXPRESSIONS)
229 log_debug ("exec: default option %s.%s",
230 r -> data.option -> option -> universe -> name,
231 r -> data.option -> option -> name);
232 goto option_statement;
233 #endif
234 case append_option_statement:
235 #if defined (DEBUG_EXPRESSIONS)
236 log_debug ("exec: append option %s.%s",
237 r -> data.option -> option -> universe -> name,
238 r -> data.option -> option -> name);
239 goto option_statement;
240 #endif
241 case prepend_option_statement:
242 #if defined (DEBUG_EXPRESSIONS)
243 log_debug ("exec: prepend option %s.%s",
244 r -> data.option -> option -> universe -> name,
245 r -> data.option -> option -> name);
246 option_statement:
247 #endif
248 set_option (r -> data.option -> option -> universe,
249 out_options, r -> data.option, r -> op);
250 break;
252 case set_statement:
253 case define_statement:
254 if (!scope) {
255 log_error ("set %s: no scope",
256 r -> data.set.name);
257 status = 0;
258 break;
260 if (!*scope) {
261 if (!binding_scope_allocate (scope, MDL)) {
262 log_error ("set %s: can't allocate scope",
263 r -> data.set.name);
264 status = 0;
265 break;
268 binding = find_binding (*scope, r -> data.set.name);
269 #if defined (DEBUG_EXPRESSIONS)
270 log_debug ("exec: set %s", r -> data.set.name);
271 #endif
272 if (!binding) {
273 binding = dmalloc (sizeof *binding, MDL);
274 if (binding) {
275 memset (binding, 0, sizeof *binding);
276 binding -> name =
277 dmalloc (strlen
278 (r -> data.set.name) + 1,
279 MDL);
280 if (binding -> name) {
281 strcpy (binding -> name,
282 r -> data.set.name);
283 binding -> next = (*scope) -> bindings;
284 (*scope) -> bindings = binding;
285 } else {
286 dfree (binding, MDL);
287 binding = (struct binding *)0;
291 if (binding) {
292 if (binding -> value)
293 binding_value_dereference
294 (&binding -> value, MDL);
295 if (r -> op == set_statement) {
296 status = (evaluate_expression
297 (&binding -> value, packet,
298 lease, client_state,
299 in_options, out_options,
300 scope, r -> data.set.expr,
301 MDL));
302 } else {
303 if (!(binding_value_allocate
304 (&binding -> value, MDL))) {
305 dfree (binding, MDL);
306 binding = (struct binding *)0;
308 if (binding -> value) {
309 binding -> value -> type =
310 binding_function;
311 (fundef_reference
312 (&binding -> value -> value.fundef,
313 r -> data.set.expr -> data.func,
314 MDL));
318 #if defined (DEBUG_EXPRESSIONS)
319 log_debug ("exec: set %s%s", r -> data.set.name,
320 (binding && status ? "" : " (failed)"));
321 #endif
322 break;
324 case unset_statement:
325 if (!scope || !*scope) {
326 status = 0;
327 break;
329 binding = find_binding (*scope, r -> data.unset);
330 if (binding) {
331 if (binding -> value)
332 binding_value_dereference
333 (&binding -> value, MDL);
334 status = 1;
335 } else
336 status = 0;
337 #if defined (DEBUG_EXPRESSIONS)
338 log_debug ("exec: unset %s: %s", r -> data.unset,
339 (status ? "found" : "not found"));
340 #endif
341 break;
343 case let_statement:
344 #if defined (DEBUG_EXPRESSIONS)
345 log_debug ("exec: let %s", r -> data.let.name);
346 #endif
347 ns = (struct binding_scope *)0;
348 binding_scope_allocate (&ns, MDL);
349 e = r;
351 next_let:
352 if (ns) {
353 binding = dmalloc (sizeof *binding, MDL);
354 memset (binding, 0, sizeof *binding);
355 if (!binding) {
356 blb:
357 binding_scope_dereference (&ns, MDL);
358 } else {
359 binding -> name =
360 dmalloc (strlen
361 (e -> data.let.name + 1),
362 MDL);
363 if (binding -> name)
364 strcpy (binding -> name,
365 e -> data.let.name);
366 else {
367 dfree (binding, MDL);
368 binding = (struct binding *)0;
369 goto blb;
372 } else
373 binding = NULL;
375 if (ns && binding) {
376 status = (evaluate_expression
377 (&binding -> value, packet, lease,
378 client_state,
379 in_options, out_options,
380 scope, e -> data.set.expr, MDL));
381 binding -> next = ns -> bindings;
382 ns -> bindings = binding;
385 #if defined (DEBUG_EXPRESSIONS)
386 log_debug ("exec: let %s%s", e -> data.let.name,
387 (binding && status ? "" : "failed"));
388 #endif
389 if (!e -> data.let.statements) {
390 } else if (e -> data.let.statements -> op ==
391 let_statement) {
392 e = e -> data.let.statements;
393 goto next_let;
394 } else if (ns) {
395 if (scope && *scope)
396 binding_scope_reference (&ns -> outer,
397 *scope, MDL);
398 execute_statements
399 (result, packet, lease,
400 client_state,
401 in_options, out_options,
402 &ns, e -> data.let.statements);
404 if (ns)
405 binding_scope_dereference (&ns, MDL);
406 break;
408 case log_statement:
409 memset (&ds, 0, sizeof ds);
410 status = (evaluate_data_expression
411 (&ds, packet,
412 lease, client_state, in_options,
413 out_options, scope, r -> data.log.expr,
414 MDL));
416 #if defined (DEBUG_EXPRESSIONS)
417 log_debug ("exec: log");
418 #endif
420 if (status) {
421 switch (r -> data.log.priority) {
422 case log_priority_fatal:
423 log_fatal ("%.*s", (int)ds.len,
424 ds.data);
425 break;
426 case log_priority_error:
427 log_error ("%.*s", (int)ds.len,
428 ds.data);
429 break;
430 case log_priority_debug:
431 log_debug ("%.*s", (int)ds.len,
432 ds.data);
433 break;
434 case log_priority_info:
435 log_info ("%.*s", (int)ds.len,
436 ds.data);
437 break;
439 data_string_forget (&ds, MDL);
442 break;
444 default:
445 log_error ("bogus statement type %d", r -> op);
446 break;
448 executable_statement_dereference (&r, MDL);
449 if (next) {
450 executable_statement_reference (&r, next, MDL);
451 executable_statement_dereference (&next, MDL);
455 return 1;
458 /* Execute all the statements in a particular scope, and all statements in
459 scopes outer from that scope, but if a particular limiting scope is
460 reached, do not execute statements in that scope or in scopes outer
461 from it. More specific scopes need to take precedence over less
462 specific scopes, so we recursively traverse the scope list, executing
463 the most outer scope first. */
465 void execute_statements_in_scope (result, packet,
466 lease, client_state, in_options, out_options,
467 scope, group, limiting_group)
468 struct binding_value **result;
469 struct packet *packet;
470 struct lease *lease;
471 struct client_state *client_state;
472 struct option_state *in_options;
473 struct option_state *out_options;
474 struct binding_scope **scope;
475 struct group *group;
476 struct group *limiting_group;
478 struct group *limit;
480 /* If we've recursed as far as we can, return. */
481 if (!group)
482 return;
484 /* As soon as we get to a scope that is outer than the limiting
485 scope, we are done. This is so that if somebody does something
486 like this, it does the expected thing:
488 domain-name "fugue.com";
489 shared-network FOO {
490 host bar {
491 domain-name "othello.fugue.com";
492 fixed-address 10.20.30.40;
494 subnet 10.20.30.0 netmask 255.255.255.0 {
495 domain-name "manhattan.fugue.com";
499 The problem with the above arrangement is that the host's
500 group nesting will be host -> shared-network -> top-level,
501 and the limiting scope when we evaluate the host's scope
502 will be the subnet -> shared-network -> top-level, so we need
503 to know when we evaluate the host's scope to stop before we
504 evaluate the shared-networks scope, because it's outer than
505 the limiting scope, which means we've already evaluated it. */
507 for (limit = limiting_group; limit; limit = limit -> next) {
508 if (group == limit)
509 return;
512 if (group -> next)
513 execute_statements_in_scope (result, packet,
514 lease, client_state,
515 in_options, out_options, scope,
516 group -> next, limiting_group);
517 execute_statements (result, packet, lease, client_state, in_options,
518 out_options, scope, group -> statements);
521 /* Dereference or free any subexpressions of a statement being freed. */
523 int executable_statement_dereference (ptr, file, line)
524 struct executable_statement **ptr;
525 const char *file;
526 int line;
528 // struct executable_statement *bp;
530 if (!ptr || !*ptr) {
531 log_error ("%s(%d): null pointer", file, line);
532 #if defined (POINTER_DEBUG)
533 abort ();
534 #else
535 return 0;
536 #endif
539 (*ptr) -> refcnt--;
540 rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
541 if ((*ptr) -> refcnt > 0) {
542 *ptr = (struct executable_statement *)0;
543 return 1;
546 if ((*ptr) -> refcnt < 0) {
547 log_error ("%s(%d): negative refcnt!", file, line);
548 #if defined (DEBUG_RC_HISTORY)
549 dump_rc_history (*ptr);
550 #endif
551 #if defined (POINTER_DEBUG)
552 abort ();
553 #else
554 return 0;
555 #endif
558 if ((*ptr) -> next)
559 executable_statement_dereference (&(*ptr) -> next, file, line);
561 switch ((*ptr) -> op) {
562 case statements_statement:
563 if ((*ptr) -> data.statements)
564 executable_statement_dereference
565 (&(*ptr) -> data.statements, file, line);
566 break;
568 case on_statement:
569 if ((*ptr) -> data.on.statements)
570 executable_statement_dereference
571 (&(*ptr) -> data.on.statements, file, line);
572 break;
574 case switch_statement:
575 if ((*ptr) -> data.s_switch.statements)
576 executable_statement_dereference
577 (&(*ptr) -> data.on.statements, file, line);
578 if ((*ptr) -> data.s_switch.expr)
579 expression_dereference (&(*ptr) -> data.s_switch.expr,
580 file, line);
581 break;
583 case case_statement:
584 if ((*ptr) -> data.s_switch.expr)
585 expression_dereference (&(*ptr) -> data.c_case,
586 file, line);
587 break;
589 case if_statement:
590 if ((*ptr) -> data.ie.expr)
591 expression_dereference (&(*ptr) -> data.ie.expr,
592 file, line);
593 if ((*ptr) -> data.ie.tc)
594 executable_statement_dereference
595 (&(*ptr) -> data.ie.tc, file, line);
596 if ((*ptr) -> data.ie.fc)
597 executable_statement_dereference
598 (&(*ptr) -> data.ie.fc, file, line);
599 break;
601 case eval_statement:
602 if ((*ptr) -> data.eval)
603 expression_dereference (&(*ptr) -> data.eval,
604 file, line);
605 break;
607 case return_statement:
608 if ((*ptr) -> data.eval)
609 expression_dereference (&(*ptr) -> data.eval,
610 file, line);
611 break;
613 case set_statement:
614 if ((*ptr)->data.set.name)
615 dfree ((*ptr)->data.set.name, file, line);
616 if ((*ptr)->data.set.expr)
617 expression_dereference (&(*ptr) -> data.set.expr,
618 file, line);
619 break;
621 case unset_statement:
622 if ((*ptr)->data.unset)
623 dfree ((*ptr)->data.unset, file, line);
624 break;
626 case supersede_option_statement:
627 case send_option_statement:
628 case default_option_statement:
629 case append_option_statement:
630 case prepend_option_statement:
631 if ((*ptr) -> data.option)
632 option_cache_dereference (&(*ptr) -> data.option,
633 file, line);
634 break;
636 default:
637 /* Nothing to do. */
638 break;
641 dfree ((*ptr), file, line);
642 *ptr = (struct executable_statement *)0;
643 return 1;
646 void write_statements (file, statements, indent)
647 FILE *file;
648 struct executable_statement *statements;
649 int indent;
651 struct executable_statement *r, *x;
652 // int result;
653 // int status;
654 const char *s, *t, *dot;
655 int col;
657 if (!statements)
658 return;
660 for (r = statements; r; r = r -> next) {
661 switch (r -> op) {
662 case statements_statement:
663 write_statements (file, r -> data.statements, indent);
664 break;
666 case on_statement:
667 indent_spaces (file, indent);
668 fprintf (file, "on ");
669 s = "";
670 if (r -> data.on.evtypes & ON_EXPIRY) {
671 fprintf (file, "%sexpiry", s);
672 s = " or ";
674 if (r -> data.on.evtypes & ON_COMMIT) {
675 fprintf (file, "%scommit", s);
676 s = "or";
678 if (r -> data.on.evtypes & ON_RELEASE) {
679 fprintf (file, "%srelease", s);
680 s = "or";
682 if (r -> data.on.statements) {
683 fprintf (file, " {");
684 write_statements (file,
685 r -> data.on.statements,
686 indent + 2);
687 indent_spaces (file, indent);
688 fprintf (file, "}");
689 } else {
690 fprintf (file, ";");
692 break;
694 case switch_statement:
695 indent_spaces (file, indent);
696 fprintf (file, "switch (");
697 col = write_expression (file,
698 r -> data.s_switch.expr,
699 indent + 7, indent + 7, 1);
700 col = token_print_indent (file, col, indent + 7,
701 "", "", ")");
702 token_print_indent (file,
703 col, indent, " ", "", "{");
704 write_statements (file, r -> data.s_switch.statements,
705 indent + 2);
706 indent_spaces (file, indent);
707 fprintf (file, "}");
708 break;
710 case case_statement:
711 indent_spaces (file, indent - 1);
712 fprintf (file, "case ");
713 col = write_expression (file,
714 r -> data.s_switch.expr,
715 indent + 5, indent + 5, 1);
716 token_print_indent (file, col, indent + 5,
717 "", "", ":");
718 break;
720 case default_statement:
721 indent_spaces (file, indent - 1);
722 fprintf (file, "default: ");
723 break;
725 case if_statement:
726 indent_spaces (file, indent);
727 fprintf (file, "if ");
728 x = r;
729 col = write_expression (file,
730 x -> data.ie.expr,
731 indent + 3, indent + 3, 1);
732 else_if:
733 token_print_indent (file, col, indent, " ", "", "{");
734 write_statements (file, x -> data.ie.tc, indent + 2);
735 if (x -> data.ie.fc &&
736 x -> data.ie.fc -> op == if_statement &&
737 !x -> data.ie.fc -> next) {
738 indent_spaces (file, indent);
739 fprintf (file, "} elsif ");
740 x = x -> data.ie.fc;
741 col = write_expression (file,
742 x -> data.ie.expr,
743 indent + 6,
744 indent + 6, 1);
745 goto else_if;
747 if (x -> data.ie.fc) {
748 indent_spaces (file, indent);
749 fprintf (file, "} else {");
750 write_statements (file, x -> data.ie.fc,
751 indent + 2);
753 indent_spaces (file, indent);
754 fprintf (file, "}");
755 break;
757 case eval_statement:
758 indent_spaces (file, indent);
759 fprintf (file, "eval ");
760 col = write_expression (file, r -> data.eval,
761 indent + 5, indent + 5, 1);
762 fprintf (file, ";");
763 break;
765 case return_statement:
766 indent_spaces (file, indent);
767 fprintf (file, "return;");
768 break;
770 case add_statement:
771 indent_spaces (file, indent);
772 fprintf (file, "add \"%s\"", r -> data.add -> name);
773 break;
775 case break_statement:
776 indent_spaces (file, indent);
777 fprintf (file, "break;");
778 break;
780 case supersede_option_statement:
781 case send_option_statement:
782 s = "supersede";
783 goto option_statement;
785 case default_option_statement:
786 s = "default";
787 goto option_statement;
789 case append_option_statement:
790 s = "append";
791 goto option_statement;
793 case prepend_option_statement:
794 s = "prepend";
795 option_statement:
796 /* Note: the reason we don't try to pretty print
797 the option here is that the format of the option
798 may change in dhcpd.conf, and then when this
799 statement was read back, it would cause a syntax
800 error. */
801 if (r -> data.option -> option -> universe ==
802 &dhcp_universe) {
803 t = "";
804 dot = "";
805 } else {
806 t = (r -> data.option -> option ->
807 universe -> name);
808 dot = ".";
810 indent_spaces (file, indent);
811 fprintf (file, "%s %s%s%s = ", s, t, dot,
812 r -> data.option -> option -> name);
813 col = (indent + strlen (s) + strlen (t) +
814 strlen (dot) + strlen (r -> data.option ->
815 option -> name) + 4);
816 if (r -> data.option -> expression)
817 write_expression
818 (file,
819 r -> data.option -> expression,
820 col, indent + 8, 1);
821 else
822 token_indent_data_string
823 (file, col, indent + 8, "", "",
824 &r -> data.option -> data);
826 fprintf (file, ";"); /* XXX */
827 break;
829 case set_statement:
830 indent_spaces (file, indent);
831 fprintf (file, "set ");
832 col = token_print_indent (file, indent + 4, indent + 4,
833 "", "", r -> data.set.name);
834 col = token_print_indent (file, col, indent + 4,
835 " ", " ", "=");
836 col = write_expression (file, r -> data.set.expr,
837 indent + 3, indent + 3, 0);
838 col = token_print_indent (file, col, indent + 4,
839 " ", "", ";");
840 break;
842 case unset_statement:
843 indent_spaces (file, indent);
844 fprintf (file, "unset ");
845 col = token_print_indent (file, indent + 6, indent + 6,
846 "", "", r -> data.set.name);
847 col = token_print_indent (file, col, indent + 6,
848 " ", "", ";");
849 break;
851 case log_statement:
852 indent_spaces (file, indent);
853 fprintf (file, "log ");
854 col = token_print_indent (file, indent + 4, indent + 4,
855 "", "", "(");
856 switch (r -> data.log.priority) {
857 case log_priority_fatal:
858 col = token_print_indent
859 (file, col, indent + 4, "",
860 " ", "fatal,");
861 break;
862 case log_priority_error:
863 col = token_print_indent
864 (file, col, indent + 4, "",
865 " ", "error,");
866 break;
867 case log_priority_debug:
868 col = token_print_indent
869 (file, col, indent + 4, "",
870 " ", "debug,");
871 break;
872 case log_priority_info:
873 col = token_print_indent
874 (file, col, indent + 4, "",
875 " ", "info,");
876 break;
878 col = write_expression (file, r -> data.log.expr,
879 indent + 4, indent + 4, 0);
880 col = token_print_indent (file, col, indent + 4,
881 "", "", ");");
883 break;
885 default:
886 log_fatal ("bogus statement type %d\n", r -> op);
891 /* Find a case statement in the sequence of executable statements that
892 matches the expression, and if found, return the following statement.
893 If no case statement matches, try to find a default statement and
894 return that (the default statement can precede all the case statements).
895 Otherwise, return the null statement. */
897 int find_matching_case (struct executable_statement **ep,
898 struct packet *packet, struct lease *lease,
899 struct client_state *client_state,
900 struct option_state *in_options,
901 struct option_state *out_options,
902 struct binding_scope **scope,
903 struct expression *expr,
904 struct executable_statement *stmt)
906 int status, sub;
907 struct executable_statement *s;
908 // unsigned long foo;
910 if (is_data_expression (expr)) {
911 // struct executable_statement *e;
912 struct data_string cd, ds;
913 memset (&ds, 0, sizeof ds);
914 memset (&cd, 0, sizeof cd);
916 status = (evaluate_data_expression (&ds, packet, lease,
917 client_state, in_options,
918 out_options, scope, expr,
919 MDL));
920 if (status) {
921 for (s = stmt; s; s = s -> next) {
922 if (s -> op == case_statement) {
923 sub = (evaluate_data_expression
924 (&cd, packet, lease, client_state,
925 in_options, out_options,
926 scope, s -> data.c_case, MDL));
927 if (sub && cd.len == ds.len &&
928 !memcmp (cd.data, ds.data, cd.len))
930 data_string_forget (&cd, MDL);
931 data_string_forget (&ds, MDL);
932 executable_statement_reference
933 (ep, s -> next, MDL);
934 return 1;
936 data_string_forget (&cd, MDL);
939 data_string_forget (&ds, MDL);
941 } else {
942 unsigned long n, c;
943 status = evaluate_numeric_expression (&n, packet, lease,
944 client_state,
945 in_options, out_options,
946 scope, expr);
948 if (status) {
949 for (s = stmt; s; s = s -> next) {
950 if (s -> op == case_statement) {
951 sub = (evaluate_numeric_expression
952 (&c, packet, lease, client_state,
953 in_options, out_options,
954 scope, s -> data.c_case));
955 if (sub && n == c) {
956 executable_statement_reference
957 (ep, s -> next, MDL);
958 return 1;
965 /* If we didn't find a matching case statement, look for a default
966 statement and return the statement following it. */
967 for (s = stmt; s; s = s -> next)
968 if (s -> op == default_statement)
969 break;
970 if (s) {
971 executable_statement_reference (ep, s -> next, MDL);
972 return 1;
974 return 0;
977 int executable_statement_foreach (struct executable_statement *stmt,
978 int (*callback) (struct
979 executable_statement *,
980 void *, int),
981 void *vp, int condp)
983 struct executable_statement *foo;
984 int ok = 0;
985 // int result;
987 for (foo = stmt; foo; foo = foo -> next) {
988 if ((*callback) (foo, vp, condp) != 0)
989 ok = 1;
990 switch (foo -> op) {
991 case null_statement:
992 break;
993 case if_statement:
994 if (executable_statement_foreach (foo -> data.ie.tc,
995 callback, vp, 1))
996 ok = 1;
997 if (executable_statement_foreach (foo -> data.ie.fc,
998 callback, vp, 1))
999 ok = 1;
1000 break;
1001 case add_statement:
1002 break;
1003 case eval_statement:
1004 break;
1005 case break_statement:
1006 break;
1007 case default_option_statement:
1008 break;
1009 case supersede_option_statement:
1010 break;
1011 case append_option_statement:
1012 break;
1013 case prepend_option_statement:
1014 break;
1015 case send_option_statement:
1016 break;
1017 case statements_statement:
1018 if ((executable_statement_foreach
1019 (foo -> data.statements, callback, vp, condp)))
1020 ok = 1;
1021 break;
1022 case on_statement:
1023 if ((executable_statement_foreach
1024 (foo -> data.on.statements, callback, vp, 1)))
1025 ok = 1;
1026 break;
1027 case switch_statement:
1028 if ((executable_statement_foreach
1029 (foo -> data.s_switch.statements, callback, vp, 1)))
1030 ok = 1;
1031 break;
1032 case case_statement:
1033 break;
1034 case default_statement:
1035 break;
1036 case set_statement:
1037 break;
1038 case unset_statement:
1039 break;
1040 case let_statement:
1041 if ((executable_statement_foreach
1042 (foo -> data.let.statements, callback, vp, 0)))
1043 ok = 1;
1044 break;
1045 case define_statement:
1046 break;
1047 case log_statement:
1048 case return_statement:
1049 break;
1052 return ok;