%{ /* This file is part of mailfrom filter. Copyright (C) 2005, 2006 Sergey Poznyakoff 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 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H # include #endif #define obstack_chunk_alloc malloc #define obstack_chunk_free free #include #include "mailfrom.h" #include "gram.h" static struct locus locus; struct obstack string_stk; void string(char *str, size_t len); void line_begin(void); void line_finish(void); void line_add(char *str, size_t len); void line_add_unescape (char *text, size_t len); const struct locus * get_locus() { return &locus; } static int keyword(int kw) { yylval.locus = locus; return kw; } %} %x COMMENT STR N [0-9][0-9]* TRIPLET [0-9]{1,3} WS [ \t][ \t]* IDENT [a-zA-Z_][a-zA-Z_0-9]+ %% /* C-style comments */ "/*" BEGIN(COMMENT); [^*\n]* /* eat anything that's not a '*' */ "*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ \n ++locus.line; "*"+"/" BEGIN(INITIAL); /* Configuration directives */ ^[ \t]*#[ \t]*pragma.*/\n parse_pragma(yytext); /* End-of-line comments */ #.*\n { locus.line++; } #.* /* end-of-file comment */; /* Reserved words */ accept return keyword(ACT_ACCEPT); reject return keyword(ACT_REJECT); tempfail return keyword(ACT_TEMPFAIL); continue return keyword(ACT_CONTINUE); discard return keyword(ACT_DISCARD); add return keyword(ADD); replace return keyword(REPLACE); delete return keyword(DELETE); if return keyword(IF); fi return keyword(FI); else return keyword(ELSE); elif return keyword(ELIF); on return keyword(ON); do return keyword(DO); done return keyword(DONE); poll return keyword(POLL); matches return keyword(MATCHES); fnmatches return keyword(FNMATCHES); when return keyword(WHEN); or return keyword(OR); and return keyword(AND); not return keyword(NOT); hostname return keyword(HOSTNAME); relayed return keyword(RELAYED); host return keyword(HOST); for return keyword(FOR); as return keyword(AS); from return keyword(FROM); rate return keyword(RATE); next return keyword(NEXT); listens return keyword(LISTENS); function return keyword(KW_FUNCTION); call return keyword(CALL); validuser return keyword(VALIDUSER); dbmap return keyword(DBMAP); /* Sendmail variables */ \$[a-zA-Z] { string(yytext+1, 1); return SYMBOL; } \$\{{IDENT}\} { string(yytext+1, yyleng - 1); return SYMBOL; } /* Numeric strings */ {N} { string(yytext, yyleng); return CODE; } {N}\.{N}\.{N} { string(yytext, yyleng); return XCODE; } {TRIPLET}\.{TRIPLET}\.{TRIPLET}\.{TRIPLET} { string(yytext, yyleng); return STRING; } /* Strings */ {IDENT} { string(yytext, yyleng); return STRING; } \"[^\\"\n]*\" { string(yytext+1, yyleng-2); return STRING; } \"[^\\"\n]*\\. { BEGIN(STR); line_begin(); line_add_unescape(yytext + 1, yyleng - 1); } [^\\"\n]*\\. { line_add_unescape(yytext, yyleng); } [^\\"\n]*\" { BEGIN(INITIAL); if (yyleng > 1) line_add(yytext, yyleng - 1); line_finish(); return STRING; } /* Other tokens */ {WS} ; \n { locus.line++; } "=" return EQ; "!=" return NE; . return yytext[0]; %% void string(char *str, size_t len) { line_begin(); line_add(str, len); line_finish(); } void line_begin() { /* nothing */ } void line_finish() { obstack_1grow(&string_stk, 0); yylval.string = obstack_finish(&string_stk); } void line_add(char *str, size_t len) { obstack_grow(&string_stk, str, len); } /* Escapes the last character from yytext */ void line_add_unescape (char *text, size_t len) { char c; line_add(text, len - 2); c = mu_argcv_unquote_char (text[len - 1]); obstack_1grow(&string_stk, c); } static void vparse_error_locus(LOCUS *loc, char *fmt, va_list ap) { int n; char buf[128]; n = snprintf(buf, sizeof buf, "%s:%lu: ", loc->file, loc->line); vsnprintf(buf + n, sizeof buf - n, fmt, ap); mu_error(buf); } void parse_error_locus(LOCUS *loc, char *fmt, ...) { va_list ap; va_start(ap, fmt); vparse_error_locus(loc, fmt, ap); va_end(ap); } void parse_error(char *fmt, ...) { va_list ap; va_start(ap, fmt); vparse_error_locus(&locus, fmt, ap); va_end(ap); } int source(char *name, int ldebug) { yy_flex_debug = ldebug; obstack_init(&string_stk); yyin = fopen(name, "r"); if (!yyin) { mu_error("cannot open file `%s': %s", name, mu_strerror(errno)); return -1; } locus.file = strdup(name); locus.line = 1; return 0; } int yywrap() { fclose(yyin); return 1; } /* End of lex.l */