Added basic code generation and debugging
Showing
9 changed files
with
460 additions
and
44 deletions
... | @@ -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 | ... | ... |
-
Please register or sign in to post a comment