From 1b57a009e0473b03e5a66657a9a2ad444ee51c0d Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Fri, 8 Nov 2002 15:53:37 +0000 Subject: Fixed grammar. Added union, types and the basic actions. --- libsieve/sieve.l | 153 ++++++++++++++++++++++++++++++++++++++++++++++++------- libsieve/sieve.y | 115 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 236 insertions(+), 32 deletions(-) (limited to 'libsieve') diff --git a/libsieve/sieve.l b/libsieve/sieve.l index 4e1d10dbb..b9e18ee60 100644 --- a/libsieve/sieve.l +++ b/libsieve/sieve.l @@ -3,16 +3,16 @@ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ @@ -25,15 +25,25 @@ #include #include #include -#include +#include +#include #include #include - - + char *sieve_filename; int sieve_line_num; ino_t sieve_source_inode; - + +static list_t string_list; + +static int number __P ((void)); +static int string __P ((void)); +static void multiline_begin __P ((void)); +static void multiline_add __P ((void)); +static void multiline_finish __P ((void)); +static void ident __P((const char *text)); +static void sieve_include __P((void)); + #ifdef FLEX_SCANNER #define xinput() (yyin ? getc(yyin) : EOF) #undef YY_INPUT @@ -185,7 +195,7 @@ struct buffer_ctx { static struct buffer_ctx *context_stack; static struct buffer_ctx *ctx_lookup __P((ino_t ino)); -static int push_source __P((char *name)); +static int push_source __P((const char *name)); static int pop_source __P((void)); struct buffer_ctx * @@ -200,7 +210,7 @@ ctx_lookup (ino_t ino) } int -push_source (char *name) +push_source (const char *name) { FILE *fp; struct buffer_ctx *ctx; @@ -300,6 +310,7 @@ pop_source () WS [ \t][ \t]* IDENT [a-zA-Z_][a-zA-Z_0-9]+ +SIZESUF [kKmMgG] %% /* C-style comments */ @@ -320,18 +331,20 @@ elsif return ELSIF; else return ELSE; anyof return ANYOF; allof return ALLOF; -true return TRUE; -false return FALSE; not return NOT; /* Other tokens */ -{IDENT} return IDENT; -:{IDENT} { return TAG; } -0[0-7]* { return NUMBER; } -0x[0-9a-fA-F][0-9a-fA-F]+ { return NUMBER; } -[1-9][0-9]* { return NUMBER; } -\"[^"\n]*\" { return STRING; } -text: { BEGIN(ML); } -.[ \t]*\n { BEGIN(INITIAL); sieve_line_num++; return MULTILINE; } +{IDENT} { ident (yytext); return IDENT; } +:{IDENT} { ident (yytext + 1); return TAG; } +0[0-7]*{SIZESUF}* { return number (); } +0x[0-9a-fA-F][0-9a-fA-F]+{SIZESUF}* { return number (); } +[1-9][0-9]*{SIZESUF}* { return number (); } +\"[^"\n]*\" { return string (); } +text: { BEGIN(ML); multiline_begin (); } +.[ \t]*\n { BEGIN(INITIAL); + sieve_line_num++; + multiline_add (); + multiline_finish (); + return MULTILINE; } .*\n { sieve_line_num++; } {WS} ; \n { sieve_line_num++; } @@ -394,5 +407,107 @@ sieve_open_source (const char *name) return push_source (name); } +int +number () +{ + char *p; + yylval.number = strtol (yytext, &p, 0); + switch (*p) + { + case 'k': + case 'K': + yylval.number *= 1024L; + break; + + case 'm': + case 'M': + yylval.number *= 1024*1024L; + break; + + case 'g': + case 'G': + yylval.number *= 1024*1024*1024L; + } + return NUMBER; +} + +int +string () +{ + yylval.string = sieve_alloc (yyleng - 1); + memcpy (yylval.string, yytext + 1, yyleng - 2); + yylval.string[yyleng - 2] = 0; + return STRING; +} + +void +multiline_add () +{ + char *s = strdup (yytext); + if (!s) + { + yyerror ("not enough memory"); + exit (1); + } + list_append (string_list, s); +} + +void +multiline_begin () +{ + int status; + + if (string_list) + sieve_slist_destroy (&string_list); + status = list_create (&string_list); + if (status) + { + sieve_error ("list_create: %s", mu_errstring (status)); + exit (1); + } +} + +void +multiline_finish () +{ + iterator_t itr; + int length = 0; + char *p; + if (!string_list || iterator_create (&itr, string_list)) + return; + /* Count number of characters in the multiline */ + for (iterator_first (itr); !iterator_is_done (itr); iterator_next (itr)) + { + char *s; + iterator_current (itr, (void **)&s); + length += strlen (s); + } + + /* Copy the contents */ + yylval.string = sieve_alloc (length + 1); + p = yylval.string; + for (iterator_first (itr); !iterator_is_done (itr); iterator_next (itr)) + { + char *s; + iterator_current (itr, (void **)&s); + strcpy (p, s); + p += strlen (s); + free (s); + } + *p = 0; + iterator_destroy (&itr); + list_destroy (&string_list); +} + +void +ident (const char *text) +{ + yylval.string = strdup (text); + if (!yylval.string) + { + yyerror ("not enough memory"); + exit (1); + } +} diff --git a/libsieve/sieve.y b/libsieve/sieve.y index 1341a5c0c..0fb8408d7 100644 --- a/libsieve/sieve.y +++ b/libsieve/sieve.y @@ -3,16 +3,16 @@ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by + it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + GNU Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ @@ -20,13 +20,32 @@ # include #endif #include +#include #include #include - %} -%token IDENT TAG NUMBER STRING MULTILINE -%token REQUIRE IF ELSIF ELSE ANYOF ALLOF TRUE FALSE NOT +%union { + char *string; + long number; + sieve_instr_t instr; + sieve_value_t *value; + list_t list; + struct { + char *ident; + list_t args; + } command; +} + +%token IDENT TAG +%token NUMBER +%token STRING MULTILINE +%token REQUIRE IF ELSIF ELSE ANYOF ALLOF NOT + +%type arg +%type slist stringlist arglist maybe_arglist +%type command + %% input : /* empty */ @@ -38,6 +57,10 @@ list : statement ; statement : REQUIRE stringlist ';' + { + sieve_require ($2); + sieve_slist_destroy ($2); + } | action ';' | IF cond block maybe_elsif maybe_else ; @@ -58,8 +81,8 @@ block : '{' list '}' ; -testlist : test - | testlist ',' test +testlist : cond + | testlist ',' cond ; cond : test @@ -68,37 +91,101 @@ cond : test | NOT cond ; -test : FALSE - | TRUE - | command +test : command + { + sieve_register_t *reg = sieve_test_lookup ($1.ident); + if (!reg) + sieve_error ("%s:%d: unknown test: %s", + sieve_filename, sieve_line_num, + $1.ident); + else if (!reg->required) + sieve_error ("%s:%d: test `%s' has not been required", + sieve_filename, sieve_line_num, + $1.ident); + /*free unneeded memory */ + } ; command : IDENT maybe_arglist + { + $$.ident = $1; + $$.args = $2; + } ; action : command + { + sieve_register_t *reg = sieve_action_lookup ($1.ident); + if (!reg) + sieve_error ("%s:%d: unknown action: %s", + sieve_filename, sieve_line_num, + $1.ident); + else if (!reg->required) + sieve_error ("%s:%d: action `%s' has not been required", + sieve_filename, sieve_line_num, + $1.ident); + /*free unneeded memory */ + } ; maybe_arglist: /* empty */ + { + $$ = NULL; + } | arglist ; arglist : arg + { + list_create (&$$); + list_append ($$, &$1); + } | arglist arg + { + list_append ($1, &$2); + $$ = $1; + } ; arg : stringlist + { + $$ = sieve_value_create (SVT_STRING_LIST, $1); + } | MULTILINE + { + $$ = sieve_value_create (SVT_STRING, $1); + } | NUMBER + { + $$ = sieve_value_create (SVT_NUMBER, &$1); + } | TAG + { + $$ = sieve_value_create (SVT_TAG, $1); + } ; stringlist : STRING + { + list_create (&$$); + list_append ($$, $1); + } | '[' slist ']' + { + $$ = $2; + } ; slist : STRING + { + list_create (&$$); + list_append ($$, $1); + } | slist ',' STRING + { + list_append ($1, $3); + $$ = $1; + } ; %% @@ -106,13 +193,15 @@ slist : STRING int yyerror (char *s) { - fprintf (stderr, "%s:%d: ", sieve_filename, sieve_line_num); - fprintf (stderr, "%s\n", s); + sieve_error ("%s:%d: %s", sieve_filename, sieve_line_num, s); + return 0; } int sieve_parse (const char *name) { + sieve_register_standard_actions (); + sieve_register_standard_tests (); sieve_open_source (name); return yyparse (); } -- cgit v1.2.1