1%{
2/*
3 * configlexer.lex - lexical analyzer for NSD config file
4 *
5 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved
6 *
7 * See LICENSE for the license.
8 *
9 */
10/* because flex keeps having sign-unsigned compare problems that are unfixed*/
11#if defined(__clang__)||(defined(__GNUC__)&&((__GNUC__ >4)||(defined(__GNUC_MINOR__)&&(__GNUC__ ==4)&&(__GNUC_MINOR__ >=2))))
12#pragma GCC diagnostic ignored "-Wsign-compare"
13#endif
14#include <ctype.h>
15#include <errno.h>
16#include <string.h>
17#include <strings.h>
18#ifdef HAVE_GLOB_H
19# include <glob.h>
20#endif
21
22#include "options.h"
23#include "configparser.h"
24
25#if 0
26#define LEXOUT(s)  printf s /* used ONLY when debugging */
27#else
28#define LEXOUT(s)
29#endif
30
31struct inc_state {
32	char* filename;
33	int line;
34	YY_BUFFER_STATE buffer;
35	struct inc_state* next;
36};
37static struct inc_state* config_include_stack = NULL;
38static int inc_depth = 0;
39
40static void config_start_include(const char* filename)
41{
42	FILE *input;
43	struct inc_state* s;
44	char* nm;
45	if(inc_depth++ > 10000000) {
46		c_error("too many include files");
47		return;
48	}
49	if(strlen(filename) == 0) {
50		c_error("empty include file name");
51		return;
52	}
53	s = (struct inc_state*)malloc(sizeof(*s));
54	if(!s) {
55		c_error("include %s: malloc failure", filename);
56		return;
57	}
58	nm = strdup(filename);
59	if(!nm) {
60		c_error("include %s: strdup failure", filename);
61		free(s);
62		return;
63	}
64	input = fopen(filename, "r");
65	if(!input) {
66		c_error("cannot open include file '%s': %s",
67			filename, strerror(errno));
68		free(s);
69		free(nm);
70		return;
71	}
72	LEXOUT(("switch_to_include_file(%s) ", filename));
73	s->filename = cfg_parser->filename;
74	s->line = cfg_parser->line;
75	s->buffer = YY_CURRENT_BUFFER;
76	s->next = config_include_stack;
77	config_include_stack = s;
78
79	cfg_parser->filename = nm;
80	cfg_parser->line = 1;
81	yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
82}
83
84static void config_start_include_glob(const char* filename)
85{
86	/* check for wildcards */
87#ifdef HAVE_GLOB
88	glob_t g;
89	int i, r, flags;
90#endif /* HAVE_GLOB */
91	if (cfg_parser->chroot) {
92		int l = strlen(cfg_parser->chroot); /* chroot has trailing slash */
93		if (strncmp(cfg_parser->chroot, filename, l) != 0) {
94			c_error("include file '%s' is not relative to chroot '%s'",
95				filename, cfg_parser->chroot);
96			return;
97		}
98		filename += l - 1; /* strip chroot without trailing slash */
99	}
100#ifdef HAVE_GLOB
101	if(!(!strchr(filename, '*') && !strchr(filename, '?') &&
102		 !strchr(filename, '[') && !strchr(filename, '{') &&
103		 !strchr(filename, '~'))) {
104		 flags = 0
105#ifdef GLOB_ERR
106		 	 | GLOB_ERR
107#endif
108			 /* do not set GLOB_NOSORT so the results are sorted
109			    and in a predictable order. */
110#ifdef GLOB_BRACE
111			 | GLOB_BRACE
112#endif
113#ifdef GLOB_TILDE
114			 | GLOB_TILDE
115#endif
116		;
117		memset(&g, 0, sizeof(g));
118		r = glob(filename, flags, NULL, &g);
119		if(r) {
120			/* some error */
121			globfree(&g);
122			if(r == GLOB_NOMATCH)
123				return; /* no matches for pattern */
124			config_start_include(filename); /* let original deal with it */
125			return;
126		}
127		/* process files found, if any */
128		for(i=(int)g.gl_pathc-1; i>=0; i--) {
129			config_start_include(g.gl_pathv[i]);
130		}
131		globfree(&g);
132		return;
133	}
134#endif /* HAVE_GLOB */
135	config_start_include(filename);
136}
137
138static void config_end_include(void)
139{
140	struct inc_state* s = config_include_stack;
141	--inc_depth;
142	if(!s) return;
143	free(cfg_parser->filename);
144	cfg_parser->filename = s->filename;
145	cfg_parser->line = s->line;
146	yy_delete_buffer(YY_CURRENT_BUFFER);
147	yy_switch_to_buffer(s->buffer);
148	config_include_stack = s->next;
149	free(s);
150}
151
152#ifndef yy_set_bol /* compat definition, for flex 2.4.6 */
153#define yy_set_bol(at_bol) \
154        { \
155	        if ( ! yy_current_buffer ) \
156	                yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
157	        yy_current_buffer->yy_ch_buf[0] = ((at_bol)?'\n':' '); \
158        }
159#endif
160
161%}
162%option noinput
163%option nounput
164%{
165#ifndef YY_NO_UNPUT
166#define YY_NO_UNPUT 1
167#endif
168#ifndef YY_NO_INPUT
169#define YY_NO_INPUT 1
170#endif
171%}
172
173SPACE   [ \t]
174LETTER  [a-zA-Z]
175UNQUOTEDLETTER [^\"\n\r \t\\]|\\.
176NEWLINE [\r\n]
177COMMENT \#
178COLON 	\:
179ANY     [^\"\n\r\\]|\\.
180
181%x	quotedstring include include_quoted
182
183%%
184{SPACE}* 		{ LEXOUT(("SP ")); /* ignore */ }
185{SPACE}*{COMMENT}.* 	{ LEXOUT(("comment(%s) ", yytext)); /* ignore */ }
186server{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_SERVER;}
187name{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_NAME;}
188ip-address{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_IP_ADDRESS;}
189interface{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_IP_ADDRESS;}
190ip-transparent{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_IP_TRANSPARENT;}
191ip-freebind{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_IP_FREEBIND;}
192send-buffer-size{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_SEND_BUFFER_SIZE;}
193receive-buffer-size{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_RECEIVE_BUFFER_SIZE;}
194debug-mode{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DEBUG_MODE;}
195use-systemd{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_USE_SYSTEMD;}
196hide-version{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_HIDE_VERSION;}
197hide-identity{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_HIDE_IDENTITY;}
198drop-updates{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DROP_UPDATES; }
199ip4-only{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_IP4_ONLY;}
200ip6-only{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_IP6_ONLY;}
201do-ip4{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_DO_IP4;}
202do-ip6{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_DO_IP6;}
203database{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_DATABASE;}
204identity{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_IDENTITY;}
205version{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_VERSION;}
206nsid{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_NSID;}
207logfile{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_LOGFILE;}
208log-only-syslog{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_LOG_ONLY_SYSLOG;}
209server-count{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_SERVER_COUNT;}
210tcp-count{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_TCP_COUNT;}
211tcp-reject-overflow{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_TCP_REJECT_OVERFLOW;}
212tcp-query-count{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_TCP_QUERY_COUNT;}
213tcp-timeout{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_TCP_TIMEOUT;}
214tcp-mss{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_TCP_MSS;}
215outgoing-tcp-mss{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_OUTGOING_TCP_MSS;}
216ipv4-edns-size{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_IPV4_EDNS_SIZE;}
217ipv6-edns-size{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_IPV6_EDNS_SIZE;}
218pidfile{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_PIDFILE;}
219port{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_PORT;}
220reuseport{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_REUSEPORT;}
221statistics{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_STATISTICS;}
222chroot{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_CHROOT;}
223username{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_USERNAME;}
224zonesdir{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_ZONESDIR;}
225zonelistfile{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_ZONELISTFILE;}
226difffile{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_DIFFFILE;}
227xfrdfile{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_XFRDFILE;}
228xfrdir{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_XFRDIR;}
229xfrd-reload-timeout{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_XFRD_RELOAD_TIMEOUT;}
230verbosity{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_VERBOSITY;}
231zone{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_ZONE;}
232zonefile{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_ZONEFILE;}
233zonestats{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_ZONESTATS;}
234allow-notify{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_ALLOW_NOTIFY;}
235size-limit-xfr{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_SIZE_LIMIT_XFR;}
236request-xfr{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_REQUEST_XFR;}
237notify{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_NOTIFY;}
238notify-retry{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_NOTIFY_RETRY;}
239provide-xfr{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_PROVIDE_XFR;}
240allow-query{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_ALLOW_QUERY;}
241outgoing-interface{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_OUTGOING_INTERFACE;}
242allow-axfr-fallback{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_ALLOW_AXFR_FALLBACK;}
243tls-auth{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_TLS_AUTH;}
244auth-domain-name{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_TLS_AUTH_DOMAIN_NAME;}
245client-cert{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_TLS_AUTH_CLIENT_CERT;}
246client-key{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_TLS_AUTH_CLIENT_KEY;}
247client-key-pw{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_TLS_AUTH_CLIENT_KEY_PW;}
248key{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_KEY;}
249algorithm{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_ALGORITHM;}
250secret{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_SECRET;}
251pattern{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_PATTERN;}
252include-pattern{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_INCLUDE_PATTERN;}
253remote-control{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_REMOTE_CONTROL;}
254control-enable{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_ENABLE;}
255control-interface{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_INTERFACE;}
256control-port{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_PORT;}
257server-key-file{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_SERVER_KEY_FILE;}
258server-cert-file{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_SERVER_CERT_FILE;}
259control-key-file{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_KEY_FILE;}
260control-cert-file{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_CERT_FILE;}
261AXFR			{ LEXOUT(("v(%s) ", yytext)); return VAR_AXFR;}
262UDP			{ LEXOUT(("v(%s) ", yytext)); return VAR_UDP;}
263rrl-size{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_RRL_SIZE;}
264rrl-ratelimit{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_RRL_RATELIMIT;}
265rrl-slip{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_RRL_SLIP;}
266rrl-ipv4-prefix-length{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_RRL_IPV4_PREFIX_LENGTH;}
267rrl-ipv6-prefix-length{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_RRL_IPV6_PREFIX_LENGTH;}
268rrl-whitelist-ratelimit{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_RRL_WHITELIST_RATELIMIT;}
269rrl-whitelist{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_RRL_WHITELIST;}
270zonefiles-check{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_ZONEFILES_CHECK;}
271zonefiles-write{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_ZONEFILES_WRITE;}
272dnstap{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP;}
273dnstap-enable{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_ENABLE;}
274dnstap-socket-path{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_SOCKET_PATH; }
275dnstap-ip{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_IP; }
276dnstap-tls{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_TLS; }
277dnstap-tls-server-name{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_TLS_SERVER_NAME; }
278dnstap-tls-cert-bundle{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_TLS_CERT_BUNDLE; }
279dnstap-tls-client-key-file{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_TLS_CLIENT_KEY_FILE; }
280dnstap-tls-client-cert-file{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_TLS_CLIENT_CERT_FILE; }
281dnstap-send-identity{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_SEND_IDENTITY; }
282dnstap-send-version{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_SEND_VERSION; }
283dnstap-identity{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_IDENTITY; }
284dnstap-version{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_VERSION; }
285dnstap-log-auth-query-messages{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_LOG_AUTH_QUERY_MESSAGES; }
286dnstap-log-auth-response-messages{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_LOG_AUTH_RESPONSE_MESSAGES; }
287log-time-ascii{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_LOG_TIME_ASCII;}
288round-robin{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_ROUND_ROBIN;}
289minimal-responses{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_MINIMAL_RESPONSES;}
290confine-to-zone{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_CONFINE_TO_ZONE;}
291refuse-any{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_REFUSE_ANY;}
292max-refresh-time{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_MAX_REFRESH_TIME;}
293min-refresh-time{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_MIN_REFRESH_TIME;}
294max-retry-time{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_MAX_RETRY_TIME;}
295min-retry-time{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_MIN_RETRY_TIME;}
296min-expire-time{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_MIN_EXPIRE_TIME;}
297store-ixfr{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_STORE_IXFR;}
298ixfr-size{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_IXFR_SIZE;}
299ixfr-number{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_IXFR_NUMBER;}
300create-ixfr{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_CREATE_IXFR;}
301multi-master-check{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_MULTI_MASTER_CHECK;}
302tls-service-key{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_TLS_SERVICE_KEY;}
303tls-service-ocsp{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_TLS_SERVICE_OCSP;}
304tls-service-pem{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_TLS_SERVICE_PEM;}
305tls-port{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_TLS_PORT;}
306tls-cert-bundle{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_TLS_CERT_BUNDLE; }
307proxy-protocol-port{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_PROXY_PROTOCOL_PORT; }
308answer-cookie{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_ANSWER_COOKIE;}
309cookie-secret{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_COOKIE_SECRET;}
310cookie-secret-file{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_COOKIE_SECRET_FILE;}
311xfrd-tcp-max{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_XFRD_TCP_MAX;}
312xfrd-tcp-pipeline{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_XFRD_TCP_PIPELINE;}
313verify{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_VERIFY; }
314enable{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_ENABLE; }
315verify-zone{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_VERIFY_ZONE; }
316verify-zones{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_VERIFY_ZONES; }
317verifier{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_VERIFIER; }
318verifier-count{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_VERIFIER_COUNT; }
319verifier-feed-zone{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_VERIFIER_FEED_ZONE; }
320verifier-timeout{COLON}		{ LEXOUT(("v(%s) ", yytext)); return VAR_VERIFIER_TIMEOUT; }
321{NEWLINE}		{ LEXOUT(("NL\n")); cfg_parser->line++;}
322
323servers={UNQUOTEDLETTER}*	{
324	yyless(yyleng - (yyleng - 8));
325	LEXOUT(("v(%s) ", yytext));
326	return VAR_SERVERS;
327}
328bindtodevice={UNQUOTEDLETTER}*	{
329	yyless(yyleng - (yyleng - 13));
330	LEXOUT(("v(%s) ", yytext));
331	return VAR_BINDTODEVICE;
332}
333setfib={UNQUOTEDLETTER}*	{
334	yyless(yyleng - (yyleng - 7));
335	LEXOUT(("v(%s) ", yytext));
336	return VAR_SETFIB;
337}
338
339cpu-affinity{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_CPU_AFFINITY; }
340xfrd-cpu-affinity{COLON}	{ LEXOUT(("v(%s) ", yytext)); return VAR_XFRD_CPU_AFFINITY; }
341server-[1-9][0-9]*-cpu-affinity{COLON}	{
342		char *str = yytext;
343		LEXOUT(("v(%s) ", yytext));
344		/* Skip server- */
345		while (*str != '\0' && (*str < '0' || *str > '9')) {
346			str++;
347		}
348		c_lval.llng = strtoll(str, NULL, 10);
349		return VAR_SERVER_CPU_AFFINITY;
350	}
351
352	/* Quoted strings. Strip leading and ending quotes */
353\"			{ BEGIN(quotedstring); LEXOUT(("QS ")); }
354<quotedstring><<EOF>>   {
355        c_error("EOF inside quoted string");
356        BEGIN(INITIAL);
357}
358<quotedstring>{ANY}*    { LEXOUT(("STR(%s) ", yytext)); yymore(); }
359<quotedstring>\n        { cfg_parser->line++; yymore(); }
360<quotedstring>\" {
361        LEXOUT(("QE "));
362        BEGIN(INITIAL);
363        yytext[yyleng - 1] = '\0';
364	c_lval.str = region_strdup(cfg_parser->opt->region, yytext);
365        return STRING;
366}
367
368	/* include: directive */
369include{COLON}		{ LEXOUT(("v(%s) ", yytext)); BEGIN(include); }
370<include><<EOF>>	{
371        c_error("EOF inside include directive");
372        BEGIN(INITIAL);
373}
374<include>{SPACE}*	{ LEXOUT(("ISP ")); /* ignore */ }
375<include>{NEWLINE}	{ LEXOUT(("NL\n")); cfg_parser->line++;}
376<include>\"		{ LEXOUT(("IQS ")); BEGIN(include_quoted); }
377<include>{UNQUOTEDLETTER}*	{
378	LEXOUT(("Iunquotedstr(%s) ", yytext));
379	config_start_include_glob(yytext);
380	BEGIN(INITIAL);
381}
382<include_quoted><<EOF>>	{
383        c_error("EOF inside quoted string");
384        BEGIN(INITIAL);
385}
386<include_quoted>{ANY}*	{ LEXOUT(("ISTR(%s) ", yytext)); yymore(); }
387<include_quoted>{NEWLINE}	{ cfg_parser->line++; yymore(); }
388<include_quoted>\"	{
389	LEXOUT(("IQE "));
390	yytext[yyleng - 1] = '\0';
391	config_start_include_glob(yytext);
392	BEGIN(INITIAL);
393}
394<INITIAL><<EOF>>	{
395	yy_set_bol(1); /* Set beginning of line, so "^" rules match.  */
396	if (!config_include_stack) {
397		yyterminate();
398	} else {
399		fclose(yyin);
400		config_end_include();
401	}
402}
403
404{UNQUOTEDLETTER}*	{ LEXOUT(("unquotedstr(%s) ", yytext));
405			c_lval.str = region_strdup(cfg_parser->opt->region, yytext); return STRING; }
406
407%%
408