Commit 2233fe22 2233fe22de4e6ff71d711b833cff595bd98b2b09 by Sergey Poznyakoff

Added basic code generation and debugging

1 parent 0ba30cb1
...@@ -16,11 +16,15 @@ ...@@ -16,11 +16,15 @@
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17 17
18 #include <sys/types.h> 18 #include <sys/types.h>
19 #include <stdarg.h>
19 #include <mailutils/mailutils.h> 20 #include <mailutils/mailutils.h>
20 21
21 typedef struct sieve_machine sieve_machine_t; 22 typedef struct sieve_machine sieve_machine_t;
22 23
23 typedef int (*sieve_instr_t) __P((sieve_machine_t *mach, list_t *args)); 24 typedef int (*sieve_handler_t) __P((sieve_machine_t *mach,
25 list_t args, list_t tags));
26 typedef int (*sieve_printf_t) __P((void *data, const char *fmt, va_list ap));
27 typedef int (*sieve_vprintf_t) __P((void *data, const char *fmt, va_list ap));
24 28
25 typedef enum { 29 typedef enum {
26 SVT_VOID, 30 SVT_VOID,
...@@ -32,12 +36,15 @@ typedef enum { ...@@ -32,12 +36,15 @@ typedef enum {
32 SVT_VALUE_LIST 36 SVT_VALUE_LIST
33 } sieve_data_type; 37 } sieve_data_type;
34 38
39 typedef struct sieve_runtime_tag sieve_runtime_tag_t;
40
35 typedef struct { 41 typedef struct {
36 sieve_data_type type; 42 sieve_data_type type;
37 union { 43 union {
38 char *string; 44 char *string;
39 long number; 45 long number;
40 list_t list; 46 list_t list;
47 sieve_runtime_tag_t *tag;
41 } v; 48 } v;
42 } sieve_value_t; 49 } sieve_value_t;
43 50
...@@ -47,10 +54,15 @@ typedef struct { ...@@ -47,10 +54,15 @@ typedef struct {
47 sieve_data_type argtype; 54 sieve_data_type argtype;
48 } sieve_tag_def_t; 55 } sieve_tag_def_t;
49 56
57 struct sieve_runtime_tag {
58 int tag;
59 sieve_value_t *arg;
60 };
61
50 typedef struct { 62 typedef struct {
51 char *name; 63 char *name;
52 int required; 64 int required;
53 sieve_instr_t instr; 65 sieve_handler_t handler;
54 int num_req_args; 66 int num_req_args;
55 sieve_data_type *req_args; 67 sieve_data_type *req_args;
56 int num_tags; 68 int num_tags;
...@@ -59,18 +71,28 @@ typedef struct { ...@@ -59,18 +71,28 @@ typedef struct {
59 71
60 72
61 void *sieve_alloc __P((size_t size)); 73 void *sieve_alloc __P((size_t size));
62 int sieve_open_source __P((const char *name)); 74 void *sieve_palloc __P((list_t *pool, size_t size));
63 int sieve_parse __P((const char *name)); 75 void *sieve_prealloc __P((list_t *pool, void *ptr, size_t size));
76 void sieve_pfree __P((list_t *pool, void *ptr));
77 char *sieve_pstrdup __P((list_t *pool, const char *str));
78
79 int sieve_compile __P((sieve_machine_t *mach, const char *name, void *data,
80 sieve_printf_t errfn));
81 void sieve_set_debug __P((sieve_machine_t *mach, sieve_printf_t debug,
82 int level));
83
64 sieve_value_t * sieve_value_create __P((sieve_data_type type, void *data)); 84 sieve_value_t * sieve_value_create __P((sieve_data_type type, void *data));
65 85
66 sieve_register_t *sieve_test_lookup __P((const char *name)); 86 sieve_register_t *sieve_test_lookup __P((const char *name));
67 sieve_register_t *sieve_action_lookup __P((const char *name)); 87 sieve_register_t *sieve_action_lookup __P((const char *name));
68 int sieve_register_test __P((const char *name, sieve_instr_t instr, 88 int sieve_register_test __P((const char *name, sieve_handler_t handler,
69 sieve_data_type *arg_types, 89 sieve_data_type *arg_types,
70 sieve_tag_def_t *tags, int required)); 90 sieve_tag_def_t *tags, int required));
71 int sieve_register_action __P((const char *name, sieve_instr_t instr, 91 int sieve_register_action __P((const char *name, sieve_handler_t handler,
72 sieve_data_type *arg_types, 92 sieve_data_type *arg_types,
73 sieve_tag_def_t *tags, int required)); 93 sieve_tag_def_t *tags, int required));
74 94
75 void sieve_slist_destroy __P((list_t *plist)); 95 void sieve_slist_destroy __P((list_t *plist));
76 void sieve_require __P((list_t slist)); 96 void sieve_require __P((list_t slist));
97
98 void sieve_abort __P((sieve_machine_t *mach));
......
...@@ -26,33 +26,39 @@ ...@@ -26,33 +26,39 @@
26 #include <sieve.h> 26 #include <sieve.h>
27 27
28 int 28 int
29 sieve_action_stop (sieve_machine_t *mach, list_t *args) 29 sieve_action_stop (sieve_machine_t *mach, list_t args, list_t tags)
30 { 30 {
31 return 0;
31 } 32 }
32 33
33 int 34 int
34 sieve_action_keep (sieve_machine_t *mach, list_t *args) 35 sieve_action_keep (sieve_machine_t *mach, list_t args, list_t tags)
35 { 36 {
37 return 0;
36 } 38 }
37 39
38 int 40 int
39 sieve_action_discard (sieve_machine_t *mach, list_t *args) 41 sieve_action_discard (sieve_machine_t *mach, list_t args, list_t tags)
40 { 42 {
43 return 0;
41 } 44 }
42 45
43 int 46 int
44 sieve_action_fileinto (sieve_machine_t *mach, list_t *args) 47 sieve_action_fileinto (sieve_machine_t *mach, list_t args, list_t tags)
45 { 48 {
49 return 0;
46 } 50 }
47 51
48 int 52 int
49 sieve_action_reject (sieve_machine_t *mach, list_t *args) 53 sieve_action_reject (sieve_machine_t *mach, list_t args, list_t tags)
50 { 54 {
55 return 0;
51 } 56 }
52 57
53 int 58 int
54 sieve_action_redirect (sieve_machine_t *mach, list_t *args) 59 sieve_action_redirect (sieve_machine_t *mach, list_t args, list_t tags)
55 { 60 {
61 return 0;
56 } 62 }
57 63
58 sieve_data_type fileinto_args[] = { 64 sieve_data_type fileinto_args[] = {
......
...@@ -35,7 +35,7 @@ sieve_lookup (list_t list, const char *name) ...@@ -35,7 +35,7 @@ sieve_lookup (list_t list, const char *name)
35 sieve_register_t *reg; 35 sieve_register_t *reg;
36 36
37 if (!list || iterator_create (&itr, list)) 37 if (!list || iterator_create (&itr, list))
38 return; 38 return NULL;
39 39
40 for (iterator_first (itr); !iterator_is_done (itr); iterator_next (itr)) 40 for (iterator_first (itr); !iterator_is_done (itr); iterator_next (itr))
41 { 41 {
...@@ -63,7 +63,7 @@ sieve_action_lookup (const char *name) ...@@ -63,7 +63,7 @@ sieve_action_lookup (const char *name)
63 63
64 static int 64 static int
65 sieve_register (list_t *list, 65 sieve_register (list_t *list,
66 const char *name, sieve_instr_t instr, 66 const char *name, sieve_handler_t handler,
67 sieve_data_type *arg_types, 67 sieve_data_type *arg_types,
68 sieve_tag_def_t *tags, int required) 68 sieve_tag_def_t *tags, int required)
69 { 69 {
...@@ -73,7 +73,7 @@ sieve_register (list_t *list, ...@@ -73,7 +73,7 @@ sieve_register (list_t *list,
73 if (!reg) 73 if (!reg)
74 return ENOMEM; 74 return ENOMEM;
75 reg->name = name; 75 reg->name = name;
76 reg->instr = instr; 76 reg->handler = handler;
77 77
78 if (arg_types) 78 if (arg_types)
79 { 79 {
...@@ -111,17 +111,17 @@ sieve_register (list_t *list, ...@@ -111,17 +111,17 @@ sieve_register (list_t *list,
111 111
112 112
113 int 113 int
114 sieve_register_test (const char *name, sieve_instr_t instr, 114 sieve_register_test (const char *name, sieve_handler_t handler,
115 sieve_data_type *arg_types, 115 sieve_data_type *arg_types,
116 sieve_tag_def_t *tags, int required) 116 sieve_tag_def_t *tags, int required)
117 { 117 {
118 return sieve_register (&test_list, name, instr, arg_types, tags, required); 118 return sieve_register (&test_list, name, handler, arg_types, tags, required);
119 } 119 }
120 120
121 int 121 int
122 sieve_register_action (const char *name, sieve_instr_t instr, 122 sieve_register_action (const char *name, sieve_handler_t handler,
123 sieve_data_type *arg_types, 123 sieve_data_type *arg_types,
124 sieve_tag_def_t *tags, int required) 124 sieve_tag_def_t *tags, int required)
125 { 125 {
126 return sieve_register (&action_list, name, instr, arg_types, tags, required); 126 return sieve_register (&action_list, name, handler, arg_types, tags, required);
127 } 127 }
......
...@@ -16,20 +16,78 @@ ...@@ -16,20 +16,78 @@
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17 17
18 #include <mailutils/libsieve.h> 18 #include <mailutils/libsieve.h>
19 #include <setjmp.h>
20
21 #define SIEVE_CODE_INCR 128
22
23 typedef void (*sieve_instr_t) __P((sieve_machine_t *mach));
19 24
20 typedef union { 25 typedef union {
21 sieve_instr_t instr; 26 sieve_instr_t instr;
22 sieve_value_t val; 27 sieve_handler_t handler;
28 sieve_value_t *val;
29 list_t list;
30 long number;
31 char *string;
23 } sieve_op_t; 32 } sieve_op_t;
24 33
25 struct sieve_machine { 34 struct sieve_machine {
26 size_t progsize; 35 list_t memory_pool; /* Pool of allocated memory objects */
27 sieve_op_t *prog; 36
37 size_t progsize; /* Number of allocated program cells */
38 size_t pc; /* Current program counter */
39 sieve_op_t *prog; /* Compiled program */
40
41 long reg; /* Numeric register */
42 list_t stack; /* Runtime stack */
43
44 int debug_level;
45
46 sieve_printf_t error_printer;
47 sieve_printf_t debug_printer;
48
49 void *data;
50
51 jmp_buf errbuf;
28 }; 52 };
29 53
30 extern char *sieve_filename; 54 extern char *sieve_filename;
31 extern int sieve_line_num; 55 extern int sieve_line_num;
32 extern int sieve_yydebug; 56 extern int sieve_yydebug;
57 extern sieve_machine_t *sieve_machine;
58 extern int sieve_error_count;
59
60 void sieve_error __P((const char *fmt, ...));
61 void sieve_debug_internal __P((sieve_printf_t printer, void *data,
62 const char *fmt, ...));
63 void sieve_debug __P((sieve_machine_t *mach, const char *fmt, ...));
64 void sieve_print_value __P((sieve_value_t *val, sieve_printf_t printer,
65 void *data));
66 void sieve_print_value_list __P((list_t list, sieve_printf_t printer,
67 void *data));
68 void sieve_print_tag_list __P((list_t list, sieve_printf_t printer,
69 void *data));
70
71 int _sieve_default_error_printer __P((void*data, const char *fmt, va_list ap));
72
73 int sieve_lex_begin __P((const char *name));
74 void sieve_lex_finish __P((void));
75
76 void sieve_register_standard_actions __P((void));
77 void sieve_register_standard_tests __P((void));
33 78
34 #define sieve_error mu_error 79 int sieve_code __P((sieve_op_t *op));
80 int sieve_code_instr __P((sieve_instr_t instr));
81 int sieve_code_handler __P((sieve_handler_t handler));
82 int sieve_code_list __P((list_t list));
83 int sieve_code_number __P((long num));
84 int sieve_code_test __P((sieve_register_t *reg, list_t arglist));
85 int sieve_code_action __P((sieve_register_t *reg, list_t arglist));
35 86
87 void instr_action __P((sieve_machine_t *mach));
88 void instr_test __P((sieve_machine_t *mach));
89 void instr_push __P((sieve_machine_t *mach));
90 void instr_pop __P((sieve_machine_t *mach));
91 void instr_allof __P((sieve_machine_t *mach));
92 void instr_anyof __P((sieve_machine_t *mach));
93 void instr_not __P((sieve_machine_t *mach));
......
...@@ -283,6 +283,7 @@ pop_source () ...@@ -283,6 +283,7 @@ pop_source ()
283 { 283 {
284 struct buffer_ctx *ctx; 284 struct buffer_ctx *ctx;
285 285
286 if (yyin)
286 fclose (yyin); 287 fclose (yyin);
287 #ifndef FLEX_SCANNER 288 #ifndef FLEX_SCANNER
288 lex_delete_buffer (current_buffer); 289 lex_delete_buffer (current_buffer);
...@@ -402,11 +403,18 @@ sieve_include () ...@@ -402,11 +403,18 @@ sieve_include ()
402 } 403 }
403 404
404 int 405 int
405 sieve_open_source (const char *name) 406 sieve_lex_begin (const char *name)
406 { 407 {
407 return push_source (name); 408 return push_source (name);
408 } 409 }
409 410
411 void
412 sieve_lex_finish ()
413 {
414 while (pop_source () == 0)
415 ;
416 }
417
410 int 418 int
411 number () 419 number ()
412 { 420 {
...@@ -434,7 +442,7 @@ number () ...@@ -434,7 +442,7 @@ number ()
434 int 442 int
435 string () 443 string ()
436 { 444 {
437 yylval.string = sieve_alloc (yyleng - 1); 445 yylval.string = sieve_palloc (&sieve_machine->memory_pool, yyleng - 1);
438 memcpy (yylval.string, yytext + 1, yyleng - 2); 446 memcpy (yylval.string, yytext + 1, yyleng - 2);
439 yylval.string[yyleng - 2] = 0; 447 yylval.string[yyleng - 2] = 0;
440 return STRING; 448 return STRING;
...@@ -486,7 +494,7 @@ multiline_finish () ...@@ -486,7 +494,7 @@ multiline_finish ()
486 } 494 }
487 495
488 /* Copy the contents */ 496 /* Copy the contents */
489 yylval.string = sieve_alloc (length + 1); 497 yylval.string = sieve_palloc (&sieve_machine->memory_pool, length + 1);
490 p = yylval.string; 498 p = yylval.string;
491 for (iterator_first (itr); !iterator_is_done (itr); iterator_next (itr)) 499 for (iterator_first (itr); !iterator_is_done (itr); iterator_next (itr))
492 { 500 {
......
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
23 #include <stdlib.h> 23 #include <stdlib.h>
24 #include <assert.h> 24 #include <assert.h>
25 #include <sieve.h> 25 #include <sieve.h>
26
27 sieve_machine_t *sieve_machine;
28 int sieve_error_count;
26 %} 29 %}
27 30
28 %union { 31 %union {
...@@ -31,6 +34,7 @@ ...@@ -31,6 +34,7 @@
31 sieve_instr_t instr; 34 sieve_instr_t instr;
32 sieve_value_t *value; 35 sieve_value_t *value;
33 list_t list; 36 list_t list;
37 size_t pc;
34 struct { 38 struct {
35 char *ident; 39 char *ident;
36 list_t args; 40 list_t args;
...@@ -45,11 +49,14 @@ ...@@ -45,11 +49,14 @@
45 %type <value> arg 49 %type <value> arg
46 %type <list> slist stringlist arglist maybe_arglist 50 %type <list> slist stringlist arglist maybe_arglist
47 %type <command> command 51 %type <command> command
52 %type <number> testlist
53 %type <pc> action test statement list
48 54
49 %% 55 %%
50 56
51 input : /* empty */ 57 input : /* empty */
52 | list 58 | list
59 { /* to placate bison */ }
53 ; 60 ;
54 61
55 list : statement 62 list : statement
...@@ -59,10 +66,15 @@ list : statement ...@@ -59,10 +66,15 @@ list : statement
59 statement : REQUIRE stringlist ';' 66 statement : REQUIRE stringlist ';'
60 { 67 {
61 sieve_require ($2); 68 sieve_require ($2);
62 sieve_slist_destroy ($2); 69 sieve_slist_destroy (&$2);
70 $$ = sieve_machine->pc;
63 } 71 }
64 | action ';' 72 | action ';'
65 | IF cond block maybe_elsif maybe_else 73 | IF cond block maybe_elsif maybe_else
74 {
75 /* FIXME!! */
76 $$ = sieve_machine->pc;
77 }
66 ; 78 ;
67 79
68 maybe_elsif : /* empty */ 80 maybe_elsif : /* empty */
...@@ -82,18 +94,45 @@ block : '{' list '}' ...@@ -82,18 +94,45 @@ block : '{' list '}'
82 94
83 95
84 testlist : cond 96 testlist : cond
97 {
98 if (sieve_code_instr (instr_push))
99 YYERROR;
100 $$ = 1;
101 }
85 | testlist ',' cond 102 | testlist ',' cond
103 {
104 if (sieve_code_instr (instr_push))
105 YYERROR;
106 $$ = $1 + 1;
107 }
86 ; 108 ;
87 109
88 cond : test 110 cond : test
111 { /* to placate bison */ }
89 | ANYOF '(' testlist ')' 112 | ANYOF '(' testlist ')'
113 {
114 if (sieve_code_instr (instr_anyof)
115 || sieve_code_number ($3))
116 YYERROR;
117 }
90 | ALLOF '(' testlist ')' 118 | ALLOF '(' testlist ')'
119 {
120 if (sieve_code_instr (instr_allof)
121 || sieve_code_number ($3))
122 YYERROR;
123 }
91 | NOT cond 124 | NOT cond
125 {
126 if (sieve_code_instr (instr_not))
127 YYERROR;
128 }
92 ; 129 ;
93 130
94 test : command 131 test : command
95 { 132 {
96 sieve_register_t *reg = sieve_test_lookup ($1.ident); 133 sieve_register_t *reg = sieve_test_lookup ($1.ident);
134 $$ = sieve_machine->pc;
135
97 if (!reg) 136 if (!reg)
98 sieve_error ("%s:%d: unknown test: %s", 137 sieve_error ("%s:%d: unknown test: %s",
99 sieve_filename, sieve_line_num, 138 sieve_filename, sieve_line_num,
...@@ -102,7 +141,8 @@ test : command ...@@ -102,7 +141,8 @@ test : command
102 sieve_error ("%s:%d: test `%s' has not been required", 141 sieve_error ("%s:%d: test `%s' has not been required",
103 sieve_filename, sieve_line_num, 142 sieve_filename, sieve_line_num,
104 $1.ident); 143 $1.ident);
105 /*free unneeded memory */ 144 if (sieve_code_test (reg, $1.args))
145 YYERROR;
106 } 146 }
107 ; 147 ;
108 148
...@@ -116,6 +156,8 @@ command : IDENT maybe_arglist ...@@ -116,6 +156,8 @@ command : IDENT maybe_arglist
116 action : command 156 action : command
117 { 157 {
118 sieve_register_t *reg = sieve_action_lookup ($1.ident); 158 sieve_register_t *reg = sieve_action_lookup ($1.ident);
159
160 $$ = sieve_machine->pc;
119 if (!reg) 161 if (!reg)
120 sieve_error ("%s:%d: unknown action: %s", 162 sieve_error ("%s:%d: unknown action: %s",
121 sieve_filename, sieve_line_num, 163 sieve_filename, sieve_line_num,
...@@ -124,7 +166,8 @@ action : command ...@@ -124,7 +166,8 @@ action : command
124 sieve_error ("%s:%d: action `%s' has not been required", 166 sieve_error ("%s:%d: action `%s' has not been required",
125 sieve_filename, sieve_line_num, 167 sieve_filename, sieve_line_num,
126 $1.ident); 168 $1.ident);
127 /*free unneeded memory */ 169 if (sieve_code_action (reg, $1.args))
170 YYERROR;
128 } 171 }
129 ; 172 ;
130 173
...@@ -138,11 +181,11 @@ maybe_arglist: /* empty */ ...@@ -138,11 +181,11 @@ maybe_arglist: /* empty */
138 arglist : arg 181 arglist : arg
139 { 182 {
140 list_create (&$$); 183 list_create (&$$);
141 list_append ($$, &$1); 184 list_append ($$, $1);
142 } 185 }
143 | arglist arg 186 | arglist arg
144 { 187 {
145 list_append ($1, &$2); 188 list_append ($1, $2);
146 $$ = $1; 189 $$ = $1;
147 } 190 }
148 ; 191 ;
...@@ -197,12 +240,42 @@ yyerror (char *s) ...@@ -197,12 +240,42 @@ yyerror (char *s)
197 return 0; 240 return 0;
198 } 241 }
199 242
243 /* FIXME: When posix thread support is added, sieve_machine_begin() should
244 aquire the global mutex, locking the current compilation session, and
245 sieve_machine_finish() should release it */
246 void
247 sieve_machine_begin (sieve_machine_t *mach, sieve_printf_t err, void *data)
248 {
249 memset (mach, 0, sizeof (*mach));
250
251 mach->error_printer = err ? err : _sieve_default_error_printer;
252 mach->data = data;
253 sieve_machine = mach;
254 sieve_error_count = 0;
255 sieve_code_instr (NULL);
256 }
257
258 void
259 sieve_machine_finish (sieve_machine_t *mach)
260 {
261 sieve_code_instr (NULL);
262 }
263
200 int 264 int
201 sieve_parse (const char *name) 265 sieve_compile (sieve_machine_t *mach, const char *name,
266 void *extra_data, sieve_printf_t err)
202 { 267 {
268 int rc;
269
270 sieve_machine_begin (mach, err, extra_data);
203 sieve_register_standard_actions (); 271 sieve_register_standard_actions ();
204 sieve_register_standard_tests (); 272 sieve_register_standard_tests ();
205 sieve_open_source (name); 273 sieve_lex_begin (name);
206 return yyparse (); 274 rc = yyparse ();
275 sieve_lex_finish ();
276 sieve_machine_finish (mach);
277 if (sieve_error_count)
278 rc = 1;
279 return rc;
207 } 280 }
208 281
......
...@@ -24,18 +24,34 @@ ...@@ -24,18 +24,34 @@
24 #include <sieve.h> 24 #include <sieve.h>
25 25
26 int 26 int
27 debug_printer (void *unused, const char *fmt, va_list ap)
28 {
29 return vfprintf (stderr, fmt, ap);
30 }
31
32 int
27 main (int argc, char **argv) 33 main (int argc, char **argv)
28 { 34 {
29 int n; 35 int n, rc, debug = 0;
36 sieve_machine_t mach;
30 37
31 assert (argc > 1); 38 assert (argc > 1);
32 if (strcmp (argv[1], "-d") == 0) 39 if (strcmp (argv[1], "-d") == 0)
33 { 40 {
34 sieve_yydebug++; 41 sieve_yydebug++;
35 n = 2; 42 n = 2;
43 debug++;
36 assert (argc > 2); 44 assert (argc > 2);
37 } 45 }
38 else 46 else
39 n = 1; 47 n = 1;
40 return sieve_parse (argv[n]); 48
49 rc = sieve_compile (&mach, argv[n], NULL, NULL);
50 if (rc == 0)
51 {
52 if (debug)
53 sieve_set_debug (&mach, debug_printer, 100);
54 sieve_run (&mach);
55 }
56 return rc;
41 } 57 }
......
...@@ -37,38 +37,45 @@ ...@@ -37,38 +37,45 @@
37 #define TAG_OVER 9 37 #define TAG_OVER 9
38 38
39 int 39 int
40 sieve_test_address (sieve_machine_t *mach, list_t *args) 40 sieve_test_address (sieve_machine_t *mach, list_t args, list_t tags)
41 { 41 {
42 return 0;
42 } 43 }
43 44
44 int 45 int
45 sieve_test_header (sieve_machine_t *mach, list_t *args) 46 sieve_test_header (sieve_machine_t *mach, list_t args, list_t tags)
46 { 47 {
48 return 0;
47 } 49 }
48 50
49 int 51 int
50 sieve_test_envelope (sieve_machine_t *mach, list_t *args) 52 sieve_test_envelope (sieve_machine_t *mach, list_t args, list_t tags)
51 { 53 {
54 return 0;
52 } 55 }
53 56
54 int 57 int
55 sieve_test_size (sieve_machine_t *mach, list_t *args) 58 sieve_test_size (sieve_machine_t *mach, list_t args, list_t tags)
56 { 59 {
60 return 0;
57 } 61 }
58 62
59 int 63 int
60 sieve_test_true (sieve_machine_t *mach, list_t *args) 64 sieve_test_true (sieve_machine_t *mach, list_t args, list_t tags)
61 { 65 {
66 return 0;
62 } 67 }
63 68
64 int 69 int
65 sieve_test_false (sieve_machine_t *mach, list_t *args) 70 sieve_test_false (sieve_machine_t *mach, list_t args, list_t tags)
66 { 71 {
72 return 0;
67 } 73 }
68 74
69 int 75 int
70 sieve_test_exists (sieve_machine_t *mach, list_t *args) 76 sieve_test_exists (sieve_machine_t *mach, list_t args, list_t tags)
71 { 77 {
78 return 0;
72 } 79 }
73 80
74 #define ADDRESS_PART \ 81 #define ADDRESS_PART \
......
...@@ -21,12 +21,13 @@ ...@@ -21,12 +21,13 @@
21 21
22 #include <stdio.h> 22 #include <stdio.h>
23 #include <stdlib.h> 23 #include <stdlib.h>
24 #include <stdarg.h>
24 #include <sieve.h> 25 #include <sieve.h>
25 26
26 void * 27 void *
27 sieve_alloc (size_t size) 28 sieve_alloc (size_t size)
28 { 29 {
29 char *p = malloc (size); 30 void *p = malloc (size);
30 if (!p) 31 if (!p)
31 { 32 {
32 mu_error ("not enough memory"); 33 mu_error ("not enough memory");
...@@ -35,6 +36,70 @@ sieve_alloc (size_t size) ...@@ -35,6 +36,70 @@ sieve_alloc (size_t size)
35 return p; 36 return p;
36 } 37 }
37 38
39 void *
40 sieve_palloc (list_t *pool, size_t size)
41 {
42 void *p = malloc (size);
43 if (p)
44 {
45 if (!*pool && list_create (pool))
46 {
47 free (p);
48 return NULL;
49 }
50 list_append (*pool, p);
51 }
52 return p;
53 }
54
55 char *
56 sieve_pstrdup (list_t *pool, const char *str)
57 {
58 size_t len;
59 char *p;
60
61 if (!str)
62 return NULL;
63 len = strlen (str);
64 p = sieve_palloc (pool, len + 1);
65 if (p)
66 {
67 memcpy (p, str, len);
68 p[len] = 0;
69 }
70 return p;
71 }
72
73 void *
74 sieve_prealloc (list_t *pool, void *ptr, size_t size)
75 {
76 void *newptr;
77
78 if (*pool)
79 list_remove (*pool, ptr);
80
81 newptr = realloc (ptr, size);
82 if (newptr)
83 {
84 if (!*pool && list_create (pool))
85 {
86 free (newptr);
87 return NULL;
88 }
89 list_append (*pool, newptr);
90 }
91 return newptr;
92 }
93
94 void
95 sieve_pfree (list_t *pool, void *ptr)
96 {
97
98 if (*pool)
99 list_remove (*pool, ptr);
100 free (ptr);
101 }
102
38 void 103 void
39 sieve_slist_destroy (list_t *plist) 104 sieve_slist_destroy (list_t *plist)
40 { 105 {
...@@ -85,3 +150,164 @@ sieve_value_create (sieve_data_type type, void *data) ...@@ -85,3 +150,164 @@ sieve_value_create (sieve_data_type type, void *data)
85 return val; 150 return val;
86 } 151 }
87 152
153 void
154 sieve_error (const char *fmt, ...)
155 {
156 va_list ap;
157
158 va_start (ap, fmt);
159 sieve_error_count++;
160 sieve_machine->error_printer (sieve_machine->data, fmt, ap);
161 va_end (ap);
162 }
163
164 void
165 sieve_debug_internal (sieve_printf_t printer, void *data, const char *fmt, ...)
166 {
167 va_list ap;
168
169 va_start (ap, fmt);
170 printer (data, fmt, ap);
171 va_end (ap);
172 }
173
174 void
175 sieve_debug (sieve_machine_t *mach, const char *fmt, ...)
176 {
177 va_list ap;
178
179 va_start (ap, fmt);
180 mach->debug_printer (mach->data, fmt, ap);
181 va_end (ap);
182 }
183
184 int
185 _sieve_default_error_printer (void *unused, const char *fmt, va_list ap)
186 {
187 return mu_verror (fmt, ap);
188 }
189
190 char *
191 sieve_type_str (sieve_data_type type)
192 {
193 switch (type)
194 {
195 case SVT_VOID:
196 return "void";
197
198 case SVT_NUMBER:
199 return "number";
200
201 case SVT_STRING:
202 return "string";
203
204 case SVT_STRING_LIST:
205 return "string-list";
206
207 case SVT_TAG:
208 return "tag";
209
210 case SVT_IDENT:
211 return "ident";
212
213 case SVT_VALUE_LIST:
214 return "value-list";
215 }
216
217 return "unknown";
218 }
219
220 struct debug_data {
221 sieve_printf_t printer;
222 void *data;
223 };
224
225 static int
226 string_printer (char *s, struct debug_data *dbg)
227 {
228 sieve_debug_internal (dbg->printer, dbg->data, "\"%s\" ", s);
229 return 0;
230 }
231
232 static int
233 value_printer (sieve_value_t *val, struct debug_data *dbg)
234 {
235 sieve_print_value (val, dbg->printer, dbg->data);
236 sieve_debug_internal (dbg->printer, dbg->data, " ");
237 return 0;
238 }
239
240 void
241 sieve_print_value (sieve_value_t *val, sieve_printf_t printer, void *data)
242 {
243 struct debug_data dbg;
244
245 dbg.printer = printer;
246 dbg.data = data;
247
248 sieve_debug_internal (printer, data, "%s(", sieve_type_str (val->type));
249 switch (val->type)
250 {
251 case SVT_VOID:
252 break;
253
254 case SVT_NUMBER:
255 sieve_debug_internal (printer, data, "%ld", val->v.number);
256 break;
257
258 case SVT_TAG:
259 case SVT_IDENT:
260 case SVT_STRING:
261 sieve_debug_internal (printer, data, "%s", val->v.string);
262 break;
263
264 case SVT_STRING_LIST:
265 list_do (val->v.list, (list_action_t*) string_printer, &dbg);
266 break;
267
268 case SVT_VALUE_LIST:
269 list_do (val->v.list, (list_action_t*) value_printer, &dbg);
270 }
271 sieve_debug_internal (printer, data, ")");
272 }
273
274 void
275 sieve_print_value_list (list_t list, sieve_printf_t printer, void *data)
276 {
277 sieve_value_t val;
278
279 val.type = SVT_VALUE_LIST;
280 val.v.list = list;
281 sieve_print_value (&val, printer, data);
282 }
283
284 static int
285 tag_printer (sieve_runtime_tag_t *val, struct debug_data *dbg)
286 {
287 sieve_debug_internal (dbg->printer, dbg->data, "%d", val->tag);
288 if (val->arg)
289 {
290 sieve_debug_internal (dbg->printer, dbg->data, "(");
291 sieve_print_value (val->arg, dbg->printer, dbg->data);
292 sieve_debug_internal (dbg->printer, dbg->data, ")");
293 }
294 sieve_debug_internal (dbg->printer, dbg->data, " ");
295 }
296
297 void
298 sieve_print_tag_list (list_t list, sieve_printf_t printer, void *data)
299 {
300 struct debug_data dbg;
301
302 dbg.printer = printer;
303 dbg.data = data;
304 list_do (list, (list_action_t*) tag_printer, &dbg);
305 }
306
307 void
308 sieve_set_debug (sieve_machine_t *mach, sieve_printf_t debug, int level)
309 {
310 mach->debug_printer = debug;
311 mach->debug_level = level;
312 }
313
......