Commit 6ac08c6e 6ac08c6e173f9b49fc5432f31482ed3e559d626c by Sergey Poznyakoff

Runtime support.

1 parent e4d186ff
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <assert.h>
24 #include <sieve.h>
25
26 #define SIEVE_ARG(m,n,t) ((m)->prog[(m)->pc+(n)].t)
27 #define SIEVE_ADJUST(m,n) (m)->pc+=(n)
28
29 #define INSTR_DEBUG(m) ((m)->debug_level == 100 && (m)->debug_printer)
30
31 static int
32 instr_run (sieve_machine_t *mach)
33 {
34 sieve_handler_t han = SIEVE_ARG (mach, 0, handler);
35 list_t arg_list = SIEVE_ARG (mach, 1, list);
36 list_t tag_list = SIEVE_ARG (mach, 2, list);
37 int rc;
38
39 if (INSTR_DEBUG (mach))
40 {
41 sieve_debug (mach, "Arguments: ");
42 sieve_print_value_list (arg_list, mach->debug_printer, mach->data);
43 sieve_debug (mach, "\nTags:");
44 sieve_print_tag_list (tag_list, mach->debug_printer, mach->data);
45 sieve_debug (mach, "\n");
46 }
47
48 rc = han (mach, arg_list, tag_list);
49 SIEVE_ADJUST(mach, 4);
50 return rc;
51 }
52
53 void
54 instr_action (sieve_machine_t *mach)
55 {
56 if (INSTR_DEBUG (mach))
57 sieve_debug (mach, "ACTION: %s\n", SIEVE_ARG (mach, 3, string));
58 instr_run (mach);
59 }
60
61 void
62 instr_test (sieve_machine_t *mach)
63 {
64 if (INSTR_DEBUG (mach))
65 sieve_debug (mach, "TEST: %s\n", SIEVE_ARG (mach, 3, string));
66 mach->reg = instr_run (mach);
67 }
68
69 void
70 instr_push (sieve_machine_t *mach)
71 {
72 if (INSTR_DEBUG (mach))
73 sieve_debug (mach, "PUSH\n");
74 if (!mach->stack && list_create (&mach->stack))
75 {
76 sieve_error ("can't create stack");
77 sieve_abort (mach);
78 }
79 list_prepend (mach->stack, (void*) mach->reg);
80 }
81
82 void
83 instr_pop (sieve_machine_t *mach)
84 {
85 if (INSTR_DEBUG (mach))
86 sieve_debug (mach, "POP\n");
87 if (!mach->stack || list_is_empty (mach->stack))
88 {
89 sieve_error ("stack underflow");
90 sieve_abort (mach);
91 }
92 list_get (mach->stack, 0, (void **)&mach->reg);
93 list_remove (mach->stack, (void *)mach->reg);
94 }
95
96 void
97 instr_allof (sieve_machine_t *mach)
98 {
99 int num = SIEVE_ARG (mach, 0, number);
100 int val = 1;
101
102 if (INSTR_DEBUG (mach))
103 sieve_debug (mach, "ALLOF %d\n", num);
104 SIEVE_ADJUST(mach, 1);
105 while (num-- > 0)
106 {
107 instr_pop (mach);
108 val &= mach->reg;
109 }
110 mach->reg = val;
111 }
112
113 void
114 instr_anyof (sieve_machine_t *mach)
115 {
116 int num = SIEVE_ARG (mach, 0, number);
117 int val = 0;
118
119 if (INSTR_DEBUG (mach))
120 sieve_debug (mach, "ANYOF %d\n", num);
121 SIEVE_ADJUST(mach, 1);
122 while (num-- > 0)
123 {
124 instr_pop (mach);
125 val &= mach->reg;
126 }
127 mach->reg = val;
128 }
129
130 void
131 instr_not (sieve_machine_t *mach)
132 {
133 if (INSTR_DEBUG (mach))
134 sieve_debug (mach, "NOT");
135 mach->reg = !mach->reg;
136 }
137
138 void
139 sieve_abort (sieve_machine_t *mach)
140 {
141 longjmp (mach->errbuf, 1);
142 }
143
144 int
145 sieve_run (sieve_machine_t *mach)
146 {
147 if (setjmp (mach->errbuf))
148 return 1;
149
150 for (mach->pc = 1; mach->prog[mach->pc].handler; )
151 (*mach->prog[mach->pc++].instr) (mach);
152
153 return 0;
154 }