summaryrefslogtreecommitdiff
path: root/lexer.l
blob: 6996a3ad39c4dd47ccf22c4b71ec7ed162da9d93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
%{
/**
 * \file lexer.l
 * Lexer for the rcfile.
 *
 * \author Adapted from fetchmail's rcfile_l.l by José Fonseca
 */


#include <stdio.h>
#include <string.h>

#include "parser.h"
#include "xmalloc.h"


int lineno = 1;

void escapes(const char *tp, char *cp, size_t n);

%}

%s NAME

%%

\"[^\"]*\"	{
			char buf[BUFSIZ];

			yytext[strlen(yytext)-1] = '\0';
			escapes(yytext+1, buf, BUFSIZ);
			yylval.sval = xstrdup(buf);
                        BEGIN(0);
			return STRING;
		}
\'[^\']*\'	{
			char buf[BUFSIZ];

			yytext[strlen(yytext)-1] = '\0';
			escapes(yytext+1, buf, BUFSIZ);
			yylval.sval = xstrdup(buf);
                        BEGIN(0);
			return STRING;
		}

<NAME>[^=;, \t\r\n]+	{
			char buf[BUFSIZ];

			escapes(yytext, buf, BUFSIZ);
			yylval.sval = xstrdup(buf);
                        BEGIN(0);
			return STRING;
		}



identity	{ BEGIN(NAME); return IDENTITY; }
host(name)?	{ BEGIN(NAME); return HOSTNAME; }
user(name)?	{ BEGIN(NAME); return USERNAME; }
pass(word)?	{ BEGIN(NAME); return PASSWORD; }
(start)?tls	{ return STARTTLS; }
(certificate_)?passphrase	{ return CERTIFICATE_PASSPHRASE; }
preconnect	{ return PRECONNECT; }
postconnect	{ return POSTCONNECT; }
qualifydomain	{ return QUALIFYDOMAIN; }
helo		{ return HELO; }
force		{ return FORCE; }
reverse_path	{ return REVERSE_PATH; }
sender		{ return SENDER; }
message_id	{ return MSGID; }
mda		{ return MDA; }
force_mda	{ return FORCE_MDA; }

=		{ return MAP; }

disabled	{ return DISABLED; }
enabled		{ return ENABLED; }
required	{ return REQUIRED; }

default		{ return DEFAULT; }

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

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

[^=;:, \t\r\n]+	{
			char buf[BUFSIZ];

			escapes(yytext, buf, BUFSIZ);
			yylval.sval = xstrdup(buf);
			return STRING;
		}

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

%%

/* process standard C-style escape sequences in a string */
void escapes(
    const char *cp,	/* source string with escapes */
    char *tp,		/* target buffer for digested string */
    size_t n
)
{
    while (*cp && --n)
    {
	int	cval = 0;

	if (*cp == '\\' && strchr("0123456789xX", cp[1]))
	{
	    char *dp;
	    const char *hex = "00112233445566778899aAbBcCdDeEfF";
	    int dcount = 0;

	    if (*++cp == 'x' || *cp == 'X')
		for (++cp; (dp = strchr(hex, *cp)) && (dcount++ < 2); cp++)
		    cval = (cval * 16) + (dp - hex) / 2;
	    else if (*cp == '0')
		while (strchr("01234567",*cp) != (char*)NULL && (dcount++ < 3))
		    cval = (cval * 8) + (*cp++ - '0');
	    else
		while ((strchr("0123456789",*cp)!=(char*)NULL)&&(dcount++ < 3))
		    cval = (cval * 10) + (*cp++ - '0');
	}
	else if (*cp == '\\')		/* C-style character escapes */
	{
	    switch (*++cp)
	    {
		case '\\': cval = '\\'; break;
		case 'n': cval = '\n'; break;
		case 't': cval = '\t'; break;
		case 'b': cval = '\b'; break;
		case 'r': cval = '\r'; break;
		default: cval = *cp;
	    }
	    cp++;
	}
	else
	    cval = *cp++;
	*tp++ = cval;
	
    }
    *tp = '\0';
}