%top{
#include "config.h"
}

%{

/*
 * rcfile_l.l -- lexer for the run control file, to be used with GNU flex.
 *
 * For license terms, see the file COPYING in this directory.
 */
#include <string.h>

#include "fetchmail.h"
#include "xmalloc.h"
#include "rcfile_y.h"

int prc_lineno = 1;

#ifdef LEXDEBUG
#define SETSTATE(n)	do {BEGIN(n); if (yydebug) fprintf(stderr, "Entering lexer state %d\n", n);} while (0)
#else
#define SETSTATE(n)	BEGIN(n)
#endif /* LEXDEBUG */

#define YY_NO_INPUT

/* #define this to emit STRING pointers and contents to stderr while lexing.
 * Useful with ASan/LSan (address/leak sanitizer) and its
 * LSAN_OPTIONS=report_objects=1 to identify where the leaked strings go. */
#undef STRING_DEBUG

%}

%option nounput noyywrap warn nodefault 8bit batch
%option header-file="rcfile_l.h"

%s NAME AUTH

%%

\"[^\"]*\"	|
\'[^\']*\'	{
			ASSERT(yyleng >= 2);
			char *in = xstrndup(yytext+1, (size_t)yyleng-2);
			escapes(in);
			yylval.sval = in;
			SETSTATE(0);
#ifdef STRING_DEBUG
			fprintf(stderr, "STRING1: %p %s\n", in, in);
#endif
			return STRING;
		}

<NAME>[^=;:, \t\r\n]+	{
			char *in = xstrdup(yytext);
			escapes(in);
			yylval.sval = in;
			SETSTATE(0);
#ifdef STRING_DEBUG
			fprintf(stderr, "STRING2: %p %s\n", in, in);
#endif
			return STRING;
		}

set		{ return SET; }
logfile		{ return LOGFILE; }
idfile		{ return IDFILE; }
pidfile		{ return PIDFILE; }
daemon		{ return DAEMON; }
syslog		{ return SYSLOG; }
invisible	{ return INVISIBLE; }
showdots	{ return SHOWDOTS; }
postmaster	{ return POSTMASTER; }
bouncemail	{ return BOUNCEMAIL; }
spambounce	{ return SPAMBOUNCE; }
softbounce	{ return SOFTBOUNCE; }
warnings	{ return WARNINGS; }
tracepolls	{ return TRACEPOLLS; }

defaults 	{ return DEFAULTS; }
server 		{ return POLL; }
poll		{ return POLL; }
skip		{ return SKIP; }
via		{ return VIA; }
aka		{ return AKA; }
local(domains)?	{ return LOCALDOMAINS; }
proto(col)? 	{ return PROTOCOL; }
service		{ return SERVICE; }
port		{ return PORT; }
interval	{ return INTERVAL; }
preauth(enticate)?	{ SETSTATE(AUTH); return AUTHENTICATE; }
auth(enticate)?	{ SETSTATE(AUTH); return AUTHENTICATE; }
any		{ SETSTATE(0); yylval.proto = A_ANY; return AUTHTYPE;}
gssapi		{ SETSTATE(0); yylval.proto = A_GSSAPI; return AUTHTYPE;}
kerberos(_v)?4	{ SETSTATE(0); yylval.proto = A_KERBEROS_V4; return AUTHTYPE;}
kerberos(_v)?5	{ SETSTATE(0); yylval.proto = A_KERBEROS_V5; return AUTHTYPE;}
kerberos	{ SETSTATE(0); yylval.proto = A_KERBEROS_V4; return AUTHTYPE;}
ssh		{ SETSTATE(0); yylval.proto = A_IMPLICIT; return AUTHTYPE;}
implicit	{ SETSTATE(0); yylval.proto = A_IMPLICIT; return AUTHTYPE;}
external	{ SETSTATE(0); yylval.proto = A_EXTERNAL; return AUTHTYPE;}
(otp|opie)	{ SETSTATE(0); yylval.proto = A_OTP; return AUTHTYPE;}
cram(-md5)?	{ SETSTATE(0); yylval.proto = A_CRAM_MD5; return AUTHTYPE;}
msn		{ SETSTATE(0); yylval.proto = A_MSN; return AUTHTYPE;}
ntlm		{ SETSTATE(0); yylval.proto = A_NTLM; return AUTHTYPE;}
<AUTH>password	{ SETSTATE(0); yylval.proto = A_PASSWORD; return AUTHTYPE;}
timeout		{ return TIMEOUT;}
idletimeout	{ return IDLETIMEOUT;}
envelope	{ return ENVELOPE; }
qvirtual	{ return QVIRTUAL; }
principal	{ return PRINCIPAL; }
esmtpname	{ return ESMTPNAME; }
esmtppassword	{ return ESMTPPASSWORD; }
bad-header	{ return BADHEADER; }
accept		{ return ACCEPT; }
reject		{ return REJECT_; }

user(name)?	{SETSTATE(NAME); return USERNAME; }
<INITIAL,NAME>pass(word)?	{SETSTATE(NAME); return PASSWORD; }
folder(s)? 	{ return FOLDER; }
smtp(host(s)?)?	{ return SMTPHOST; }
fetchdomains	{ return FETCHDOMAINS; }
smtpaddress	{ return SMTPADDRESS; }
smtpname	{ return SMTPNAME; }
antispam	{ return SPAMRESPONSE; }
mda		{ return MDA; }
bsmtp		{ return BSMTP; }
lmtp		{ return LMTP; }
pre(connect)?	{ return PRECONNECT; }
post(connect)?	{ return POSTCONNECT; }
interface	{ return INTERFACE; }
monitor		{ return MONITOR; }
plugin		{ return PLUGIN; }
plugout		{ return PLUGOUT; }
batchlimit	{ return BATCHLIMIT; }
fetchlimit	{ return FETCHLIMIT; }
fetchsizelimit	{ return FETCHSIZELIMIT; }
fastuidl	{ return FASTUIDL; }
expunge		{ return EXPUNGE; }
properties	{ return PROPERTIES; }

is		{ SETSTATE(NAME); return IS; }
here		{ return HERE; }
there		{ return THERE; }
to		{ SETSTATE(NAME); return TO; }
=		{ SETSTATE(NAME); return MAP; }

nobouncemail	|
nouidl		|
nocheckalias	|
nodns		|
noenvelope	|
nokeep		|
noflush		|
nolimitflush	|
nofetchall	|
norewrite	|
noforcecr	|
nostripcr	|
nopass8(bits)?	|
nodropstatus	|
nodropdelivered	|
nomimedec(ode)? |
nospambounce	|
noidle	        |
noforceidle	{
                   yyless(2);
                   return NO;
                }

no		{return NO;}

keep		{ return KEEP; }
moveto		{ return MOVETO; }
flush		{ return FLUSH; }
limitflush	{ return LIMITFLUSH; }
fetchall	{ return FETCHALL; }
rewrite		{ return REWRITE; }
forcecr		{ return FORCECR; }
stripcr		{ return STRIPCR; }
pass8(bits)?	{ return PASS8BITS; }
dropstatus	{ return DROPSTATUS; }
dropdelivered   { return DROPDELIVERED; }
mimedec(ode)?   { return MIMEDECODE; }
idle		{ return IDLE; }
forceidle	{ return FORCEIDLE; }
dns		{ return DNS; }
uidl		{ return UIDL; }
ssl		{ return SSL; }
sslkey		{ return SSLKEY; }
sslcert		{ return SSLCERT; }
sslproto	{ return SSLPROTO; }
sslcertck	{ return SSLCERTCK; }
sslcertfile	{ return SSLCERTFILE; }
sslcertpath	{ return SSLCERTPATH; }
sslcommonname	{ return SSLCOMMONNAME; }
sslfingerprint	{ return SSLFINGERPRINT; }
checkalias	{ return CHECKALIAS; }

limit		{ return LIMIT; }

with		{/* EMPTY */}
and		{/* EMPTY */}
has		{/* EMPTY */}
wants		{/* EMPTY */}
options		{/* EMPTY */}
[;:,]		{/* EMPTY */}

(auto)|(AUTO)	{ yylval.proto = P_AUTO;  return PROTO; }
(pop2)|(POP2)	{ yylval.proto = P_POP2;  return PROTO; }
(sdps)|(SDPS)   { return SDPS; }
(pop3)|(POP3)	{ yylval.proto = P_POP3;  return PROTO; }
(imap)|(IMAP)	{ yylval.proto = P_IMAP;  return PROTO; }
(apop)|(APOP)   { yylval.proto = P_APOP;  return PROTO; }
(rpop)|(RPOP)   { yylval.proto = P_RPOP;  return PROTO; }
(etrn)|(ETRN)   { yylval.proto = P_ETRN;  return PROTO; }
(odmr)|(ODMR)   { yylval.proto = P_ODMR;  return PROTO; }
(kpop)|(KPOP)	{ return KPOP; }

(#.*)?\\?\n	{ prc_lineno++;	}   /* newline is ignored */

-?[0-9]+	{ yylval.number = atoi(yytext); return NUMBER; }

[^=;:, \t\r\n]+	{
			char *in = xstrdup(yytext);
			escapes(in);
			yylval.sval = in;
#ifdef STRING_DEBUG
			fprintf(stderr, "STRING3: %p %s\n", in, in);
#endif
			return STRING;
		}

[ \t\r]+	;	/* whitespace */

%%
