xref: /openbsd-src/usr.sbin/nsd/zlexer.lex (revision de04d85599998336805cbff9bf6a5b3e06bf78d2)
162ac0c33Sjakob %{
262ac0c33Sjakob /*
362ac0c33Sjakob  * zlexer.lex - lexical analyzer for (DNS) zone files
462ac0c33Sjakob  *
5d3fecca9Ssthen  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved
662ac0c33Sjakob  *
762ac0c33Sjakob  * See LICENSE for the license.
862ac0c33Sjakob  *
962ac0c33Sjakob  */
108d298c9fSsthen /* because flex keeps having sign-unsigned compare problems that are unfixed*/
118d298c9fSsthen #if defined(__clang__)||(defined(__GNUC__)&&((__GNUC__ >4)||(defined(__GNUC_MINOR__)&&(__GNUC__ ==4)&&(__GNUC_MINOR__ >=2))))
128d298c9fSsthen #pragma GCC diagnostic ignored "-Wsign-compare"
138d298c9fSsthen #endif
148d298c9fSsthen /* ignore fallthrough warnings in the generated parse code case statements */
158d298c9fSsthen #if defined(__clang__)||(defined(__GNUC__)&&(__GNUC__ >=7))
168d298c9fSsthen #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
178d298c9fSsthen #endif
1862ac0c33Sjakob 
19aee1b7aaSsthen #include "config.h"
2062ac0c33Sjakob 
2162ac0c33Sjakob #include <ctype.h>
2262ac0c33Sjakob #include <errno.h>
2362ac0c33Sjakob #include <string.h>
2462ac0c33Sjakob #include <strings.h>
2562ac0c33Sjakob 
2662ac0c33Sjakob #include "zonec.h"
2762ac0c33Sjakob #include "dname.h"
2862ac0c33Sjakob #include "zparser.h"
2962ac0c33Sjakob 
3062ac0c33Sjakob #if 0
3162ac0c33Sjakob #define LEXOUT(s)  printf s /* used ONLY when debugging */
3262ac0c33Sjakob #else
3362ac0c33Sjakob #define LEXOUT(s)
3462ac0c33Sjakob #endif
3562ac0c33Sjakob 
3662ac0c33Sjakob enum lexer_state {
3762ac0c33Sjakob 	EXPECT_OWNER,
3862ac0c33Sjakob 	PARSING_OWNER,
3962ac0c33Sjakob 	PARSING_TTL_CLASS_TYPE,
4062ac0c33Sjakob 	PARSING_RDATA
4162ac0c33Sjakob };
4262ac0c33Sjakob 
4362ac0c33Sjakob static int parse_token(int token, char *yytext, enum lexer_state *lexer_state);
4462ac0c33Sjakob 
4562ac0c33Sjakob static YY_BUFFER_STATE include_stack[MAXINCLUDES];
4662ac0c33Sjakob static zparser_type zparser_stack[MAXINCLUDES];
4762ac0c33Sjakob static int include_stack_ptr = 0;
4862ac0c33Sjakob 
4962ac0c33Sjakob /*
5062ac0c33Sjakob  * Saves the file specific variables on the include stack.
5162ac0c33Sjakob  */
5262ac0c33Sjakob static void
push_parser_state(FILE * input)5362ac0c33Sjakob push_parser_state(FILE *input)
5462ac0c33Sjakob {
5562ac0c33Sjakob 	zparser_stack[include_stack_ptr].filename = parser->filename;
5662ac0c33Sjakob 	zparser_stack[include_stack_ptr].line = parser->line;
5762ac0c33Sjakob 	zparser_stack[include_stack_ptr].origin = parser->origin;
5862ac0c33Sjakob 	include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
5962ac0c33Sjakob 	yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
6062ac0c33Sjakob 	++include_stack_ptr;
6162ac0c33Sjakob }
6262ac0c33Sjakob 
6362ac0c33Sjakob /*
6462ac0c33Sjakob  * Restores the file specific variables from the include stack.
6562ac0c33Sjakob  */
6662ac0c33Sjakob static void
pop_parser_state(void)6762ac0c33Sjakob pop_parser_state(void)
6862ac0c33Sjakob {
69eab1363eSsthen 	if (parser->filename)
70eab1363eSsthen 		region_recycle(parser->region, (void *)parser->filename,
71eab1363eSsthen 			strlen(parser->filename)+1);
72eab1363eSsthen 
7362ac0c33Sjakob 	--include_stack_ptr;
7462ac0c33Sjakob 	parser->filename = zparser_stack[include_stack_ptr].filename;
7562ac0c33Sjakob 	parser->line = zparser_stack[include_stack_ptr].line;
7662ac0c33Sjakob 	parser->origin = zparser_stack[include_stack_ptr].origin;
7762ac0c33Sjakob 	yy_delete_buffer(YY_CURRENT_BUFFER);
7862ac0c33Sjakob 	yy_switch_to_buffer(include_stack[include_stack_ptr]);
7962ac0c33Sjakob }
8062ac0c33Sjakob 
81d3fecca9Ssthen static YY_BUFFER_STATE oldstate;
82d3fecca9Ssthen /* Start string scan */
83d3fecca9Ssthen void
parser_push_stringbuf(char * str)84d3fecca9Ssthen parser_push_stringbuf(char* str)
85d3fecca9Ssthen {
86d3fecca9Ssthen 	oldstate = YY_CURRENT_BUFFER;
87d3fecca9Ssthen 	yy_switch_to_buffer(yy_scan_string(str));
88d3fecca9Ssthen }
89d3fecca9Ssthen 
90d3fecca9Ssthen void
parser_pop_stringbuf(void)91d3fecca9Ssthen parser_pop_stringbuf(void)
92d3fecca9Ssthen {
93d3fecca9Ssthen 	yy_delete_buffer(YY_CURRENT_BUFFER);
94d3fecca9Ssthen 	yy_switch_to_buffer(oldstate);
95d3fecca9Ssthen 	oldstate = NULL;
96d3fecca9Ssthen }
97d3fecca9Ssthen 
98ee5153b7Sflorian 	static int paren_open = 0;
99ee5153b7Sflorian 	static enum lexer_state lexer_state = EXPECT_OWNER;
100ee5153b7Sflorian void
parser_flush(void)101ee5153b7Sflorian parser_flush(void)
102ee5153b7Sflorian {
103ee5153b7Sflorian 	YY_FLUSH_BUFFER;
104ee5153b7Sflorian 	paren_open = 0;
105ee5153b7Sflorian 	lexer_state = EXPECT_OWNER;
106ee5153b7Sflorian }
107ee5153b7Sflorian 
at_eof(void)108*de04d855Ssthen int at_eof(void)
109*de04d855Ssthen {
110*de04d855Ssthen 	static int once = 1;
111*de04d855Ssthen 	return (once = !once) ? 0 : NL;
112*de04d855Ssthen }
113*de04d855Ssthen 
11462ac0c33Sjakob #ifndef yy_set_bol /* compat definition, for flex 2.4.6 */
11562ac0c33Sjakob #define yy_set_bol(at_bol) \
11662ac0c33Sjakob 	{ \
11762ac0c33Sjakob 		if ( ! yy_current_buffer ) \
11862ac0c33Sjakob 			yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
11962ac0c33Sjakob 		yy_current_buffer->yy_ch_buf[0] = ((at_bol)?'\n':' '); \
12062ac0c33Sjakob 	}
12162ac0c33Sjakob #endif
12262ac0c33Sjakob 
12362ac0c33Sjakob %}
124d3fecca9Ssthen %option noinput
125d3fecca9Ssthen %option nounput
126d3fecca9Ssthen %{
127d3fecca9Ssthen #ifndef YY_NO_UNPUT
128d3fecca9Ssthen #define YY_NO_UNPUT 1
129d3fecca9Ssthen #endif
130d3fecca9Ssthen #ifndef YY_NO_INPUT
131d3fecca9Ssthen #define YY_NO_INPUT 1
132d3fecca9Ssthen #endif
133d3fecca9Ssthen %}
13462ac0c33Sjakob 
13562ac0c33Sjakob SPACE   [ \t]
13662ac0c33Sjakob LETTER  [a-zA-Z]
13762ac0c33Sjakob NEWLINE [\n\r]
13815ed76cbSbrad ZONESTR [^ \t\n\r();.\"\$]|\\.|\\\n
1398d298c9fSsthen CHARSTR [^ \t\n\r();.\"]|\\.|\\\n
14015ed76cbSbrad QUOTE   \"
14162ac0c33Sjakob DOLLAR  \$
14262ac0c33Sjakob COMMENT ;
14362ac0c33Sjakob DOT     \.
14462ac0c33Sjakob BIT	[^\]\n]|\\.
14562ac0c33Sjakob ANY     [^\"\n\\]|\\.
14662ac0c33Sjakob 
14762ac0c33Sjakob %x	incl bitlabel quotedstring
14862ac0c33Sjakob 
14962ac0c33Sjakob %%
15062ac0c33Sjakob {SPACE}*{COMMENT}.*	/* ignore */
15162ac0c33Sjakob ^{DOLLAR}TTL            { lexer_state = PARSING_RDATA; return DOLLAR_TTL; }
15262ac0c33Sjakob ^{DOLLAR}ORIGIN         { lexer_state = PARSING_RDATA; return DOLLAR_ORIGIN; }
15362ac0c33Sjakob 
15462ac0c33Sjakob 	/*
15562ac0c33Sjakob 	 * Handle $INCLUDE directives.  See
15662ac0c33Sjakob 	 * http://dinosaur.compilertools.net/flex/flex_12.html#SEC12.
15762ac0c33Sjakob 	 */
15862ac0c33Sjakob ^{DOLLAR}INCLUDE        {
15962ac0c33Sjakob 	BEGIN(incl);
1608d298c9fSsthen 	/* ignore case statement fallthrough on incl<EOF> flex rule */
16162ac0c33Sjakob }
16262ac0c33Sjakob <incl>\n		|
16362ac0c33Sjakob <incl><<EOF>>		{
16462ac0c33Sjakob 	int error_occurred = parser->error_occurred;
16562ac0c33Sjakob 	BEGIN(INITIAL);
16662ac0c33Sjakob 	zc_error("missing file name in $INCLUDE directive");
16762ac0c33Sjakob 	yy_set_bol(1); /* Set beginning of line, so "^" rules match.  */
16862ac0c33Sjakob 	++parser->line;
16962ac0c33Sjakob 	parser->error_occurred = error_occurred;
17062ac0c33Sjakob }
17162ac0c33Sjakob <incl>.+ 		{
17262ac0c33Sjakob 	char *tmp;
17362ac0c33Sjakob 	domain_type *origin = parser->origin;
17462ac0c33Sjakob 	int error_occurred = parser->error_occurred;
17562ac0c33Sjakob 
17662ac0c33Sjakob 	BEGIN(INITIAL);
17762ac0c33Sjakob 	if (include_stack_ptr >= MAXINCLUDES ) {
17862ac0c33Sjakob 		zc_error("includes nested too deeply, skipped (>%d)",
17962ac0c33Sjakob 			 MAXINCLUDES);
18062ac0c33Sjakob 	} else {
18162ac0c33Sjakob 		FILE *input;
18262ac0c33Sjakob 
18362ac0c33Sjakob 		/* Remove trailing comment.  */
18462ac0c33Sjakob 		tmp = strrchr(yytext, ';');
18562ac0c33Sjakob 		if (tmp) {
18662ac0c33Sjakob 			*tmp = '\0';
18762ac0c33Sjakob 		}
18862ac0c33Sjakob 		strip_string(yytext);
18962ac0c33Sjakob 
19062ac0c33Sjakob 		/* Parse origin for include file.  */
19162ac0c33Sjakob 		tmp = strrchr(yytext, ' ');
19262ac0c33Sjakob 		if (!tmp) {
19362ac0c33Sjakob 			tmp = strrchr(yytext, '\t');
19462ac0c33Sjakob 		}
19562ac0c33Sjakob 		if (tmp) {
19662ac0c33Sjakob 			const dname_type *dname;
19762ac0c33Sjakob 
19862ac0c33Sjakob 			/* split the original yytext */
19962ac0c33Sjakob 			*tmp = '\0';
20062ac0c33Sjakob 			strip_string(yytext);
20162ac0c33Sjakob 
20262ac0c33Sjakob 			dname = dname_parse(parser->region, tmp + 1);
20362ac0c33Sjakob 			if (!dname) {
20462ac0c33Sjakob 				zc_error("incorrect include origin '%s'",
20562ac0c33Sjakob 					 tmp + 1);
2060c2b6c02Sjakob 			} else if (*(tmp + strlen(tmp + 1)) != '.') {
2070c2b6c02Sjakob 				zc_error("$INCLUDE directive requires absolute domain name");
20862ac0c33Sjakob 			} else {
20962ac0c33Sjakob 				origin = domain_table_insert(
21062ac0c33Sjakob 					parser->db->domains, dname);
21162ac0c33Sjakob 			}
21262ac0c33Sjakob 		}
21362ac0c33Sjakob 
21462ac0c33Sjakob 		if (strlen(yytext) == 0) {
21562ac0c33Sjakob 			zc_error("missing file name in $INCLUDE directive");
21662ac0c33Sjakob 		} else if (!(input = fopen(yytext, "r"))) {
21762ac0c33Sjakob 			zc_error("cannot open include file '%s': %s",
21862ac0c33Sjakob 				 yytext, strerror(errno));
21962ac0c33Sjakob 		} else {
22062ac0c33Sjakob 			/* Initialize parser for include file.  */
22162ac0c33Sjakob 			char *filename = region_strdup(parser->region, yytext);
22262ac0c33Sjakob 			push_parser_state(input); /* Destroys yytext.  */
22362ac0c33Sjakob 			parser->filename = filename;
22462ac0c33Sjakob 			parser->line = 1;
22562ac0c33Sjakob 			parser->origin = origin;
22662ac0c33Sjakob 			lexer_state = EXPECT_OWNER;
22762ac0c33Sjakob 		}
22862ac0c33Sjakob 	}
22962ac0c33Sjakob 
23062ac0c33Sjakob 	parser->error_occurred = error_occurred;
23162ac0c33Sjakob }
23262ac0c33Sjakob <INITIAL><<EOF>>	{
233*de04d855Ssthen 	int eo = at_eof();
23462ac0c33Sjakob 	yy_set_bol(1); /* Set beginning of line, so "^" rules match.  */
23562ac0c33Sjakob 	if (include_stack_ptr == 0) {
236*de04d855Ssthen 		if(eo == NL)
237*de04d855Ssthen 			return eo;
23862ac0c33Sjakob 		yyterminate();
23962ac0c33Sjakob 	} else {
24062ac0c33Sjakob 		fclose(yyin);
24162ac0c33Sjakob 		pop_parser_state();
242*de04d855Ssthen 		if(eo == NL)
243*de04d855Ssthen 			return eo;
24462ac0c33Sjakob 	}
24562ac0c33Sjakob }
24662ac0c33Sjakob ^{DOLLAR}{LETTER}+	{ zc_warning("Unknown directive: %s", yytext); }
24762ac0c33Sjakob {DOT}	{
24862ac0c33Sjakob 	LEXOUT((". "));
24962ac0c33Sjakob 	return parse_token('.', yytext, &lexer_state);
25062ac0c33Sjakob }
25162ac0c33Sjakob @	{
25262ac0c33Sjakob 	LEXOUT(("@ "));
25362ac0c33Sjakob 	return parse_token('@', yytext, &lexer_state);
25462ac0c33Sjakob }
25562ac0c33Sjakob \\#	{
25662ac0c33Sjakob 	LEXOUT(("\\# "));
25762ac0c33Sjakob 	return parse_token(URR, yytext, &lexer_state);
25862ac0c33Sjakob }
25962ac0c33Sjakob {NEWLINE}	{
26062ac0c33Sjakob 	++parser->line;
26162ac0c33Sjakob 	if (!paren_open) {
26262ac0c33Sjakob 		lexer_state = EXPECT_OWNER;
26362ac0c33Sjakob 		LEXOUT(("NL\n"));
26462ac0c33Sjakob 		return NL;
26562ac0c33Sjakob 	} else {
26662ac0c33Sjakob 		LEXOUT(("SP "));
26762ac0c33Sjakob 		return SP;
26862ac0c33Sjakob 	}
26962ac0c33Sjakob }
27062ac0c33Sjakob \(	{
27162ac0c33Sjakob 	if (paren_open) {
27262ac0c33Sjakob 		zc_error("nested parentheses");
27362ac0c33Sjakob 		yyterminate();
27462ac0c33Sjakob 	}
27562ac0c33Sjakob 	LEXOUT(("( "));
27662ac0c33Sjakob 	paren_open = 1;
27762ac0c33Sjakob 	return SP;
27862ac0c33Sjakob }
27962ac0c33Sjakob \)	{
28062ac0c33Sjakob 	if (!paren_open) {
28162ac0c33Sjakob 		zc_error("closing parentheses without opening parentheses");
28262ac0c33Sjakob 		yyterminate();
28362ac0c33Sjakob 	}
28462ac0c33Sjakob 	LEXOUT((") "));
28562ac0c33Sjakob 	paren_open = 0;
28662ac0c33Sjakob 	return SP;
28762ac0c33Sjakob }
28862ac0c33Sjakob {SPACE}+	{
28962ac0c33Sjakob 	if (!paren_open && lexer_state == EXPECT_OWNER) {
29062ac0c33Sjakob 		lexer_state = PARSING_TTL_CLASS_TYPE;
29162ac0c33Sjakob 		LEXOUT(("PREV "));
29262ac0c33Sjakob 		return PREV;
29362ac0c33Sjakob 	}
29462ac0c33Sjakob 	if (lexer_state == PARSING_OWNER) {
29562ac0c33Sjakob 		lexer_state = PARSING_TTL_CLASS_TYPE;
29662ac0c33Sjakob 	}
29762ac0c33Sjakob 	LEXOUT(("SP "));
29862ac0c33Sjakob 	return SP;
29962ac0c33Sjakob }
30062ac0c33Sjakob 
30162ac0c33Sjakob 	/* Bitlabels.  Strip leading and ending brackets.  */
30262ac0c33Sjakob \\\[			{ BEGIN(bitlabel); }
30362ac0c33Sjakob <bitlabel><<EOF>>	{
30462ac0c33Sjakob 	zc_error("EOF inside bitlabel");
30562ac0c33Sjakob 	BEGIN(INITIAL);
306d3fecca9Ssthen 	yyrestart(yyin); /* this is so that lex does not give an internal err */
307d3fecca9Ssthen 	yyterminate();
30862ac0c33Sjakob }
30962ac0c33Sjakob <bitlabel>{BIT}*	{ yymore(); }
31062ac0c33Sjakob <bitlabel>\n		{ ++parser->line; yymore(); }
31162ac0c33Sjakob <bitlabel>\]		{
31262ac0c33Sjakob 	BEGIN(INITIAL);
31362ac0c33Sjakob 	yytext[yyleng - 1] = '\0';
31462ac0c33Sjakob 	return parse_token(BITLAB, yytext, &lexer_state);
31562ac0c33Sjakob }
31662ac0c33Sjakob 
31762ac0c33Sjakob 	/* Quoted strings.  Strip leading and ending quotes.  */
31815ed76cbSbrad {QUOTE}			{ BEGIN(quotedstring); LEXOUT(("\" ")); }
31962ac0c33Sjakob <quotedstring><<EOF>> 	{
32062ac0c33Sjakob 	zc_error("EOF inside quoted string");
32162ac0c33Sjakob 	BEGIN(INITIAL);
322d3fecca9Ssthen 	yyrestart(yyin); /* this is so that lex does not give an internal err */
323d3fecca9Ssthen 	yyterminate();
32462ac0c33Sjakob }
3258d298c9fSsthen <quotedstring>{ANY}*	{ LEXOUT(("QSTR ")); yymore(); }
32662ac0c33Sjakob <quotedstring>\n 	{ ++parser->line; yymore(); }
32715ed76cbSbrad <quotedstring>{QUOTE} {
32862ac0c33Sjakob 	LEXOUT(("\" "));
32962ac0c33Sjakob 	BEGIN(INITIAL);
33062ac0c33Sjakob 	yytext[yyleng - 1] = '\0';
3318d298c9fSsthen 	return parse_token(QSTR, yytext, &lexer_state);
33262ac0c33Sjakob }
33362ac0c33Sjakob 
33415ed76cbSbrad {ZONESTR}({CHARSTR})* {
33562ac0c33Sjakob 	/* Any allowed word.  */
33662ac0c33Sjakob 	return parse_token(STR, yytext, &lexer_state);
33762ac0c33Sjakob }
33862ac0c33Sjakob . {
33962ac0c33Sjakob 	zc_error("unknown character '%c' (\\%03d) seen - is this a zonefile?",
34062ac0c33Sjakob 		 (int) yytext[0], (int) yytext[0]);
34162ac0c33Sjakob }
34262ac0c33Sjakob %%
34362ac0c33Sjakob 
34462ac0c33Sjakob /*
34562ac0c33Sjakob  * Analyze "word" to see if it matches an RR type, possibly by using
34662ac0c33Sjakob  * the "TYPExxx" notation.  If it matches, the corresponding token is
34762ac0c33Sjakob  * returned and the TYPE parameter is set to the RR type value.
34862ac0c33Sjakob  */
34962ac0c33Sjakob static int
35062ac0c33Sjakob rrtype_to_token(const char *word, uint16_t *type)
35162ac0c33Sjakob {
35262ac0c33Sjakob 	uint16_t t = rrtype_from_string(word);
35362ac0c33Sjakob 	if (t != 0) {
35462ac0c33Sjakob 		rrtype_descriptor_type *entry = rrtype_descriptor_by_type(t);
35562ac0c33Sjakob 		*type = t;
35662ac0c33Sjakob 		return entry->token;
35762ac0c33Sjakob 	}
35862ac0c33Sjakob 
35962ac0c33Sjakob 	return 0;
36062ac0c33Sjakob }
36162ac0c33Sjakob 
36262ac0c33Sjakob 
36362ac0c33Sjakob /*
36462ac0c33Sjakob  * Remove \DDD constructs from the input. See RFC 1035, section 5.1.
36562ac0c33Sjakob  */
36662ac0c33Sjakob static size_t
36762ac0c33Sjakob zoctet(char *text)
36862ac0c33Sjakob {
36962ac0c33Sjakob 	/*
37062ac0c33Sjakob 	 * s follows the string, p lags behind and rebuilds the new
37162ac0c33Sjakob 	 * string
37262ac0c33Sjakob 	 */
37362ac0c33Sjakob 	char *s;
37462ac0c33Sjakob 	char *p;
37562ac0c33Sjakob 
37662ac0c33Sjakob 	for (s = p = text; *s; ++s, ++p) {
37762ac0c33Sjakob 		assert(p <= s);
37862ac0c33Sjakob 		if (s[0] != '\\') {
37962ac0c33Sjakob 			/* Ordinary character.  */
38062ac0c33Sjakob 			*p = *s;
38182cafdebSmillert 		} else if (isdigit((unsigned char)s[1]) && isdigit((unsigned char)s[2]) && isdigit((unsigned char)s[3])) {
38262ac0c33Sjakob 			/* \DDD escape.  */
38362ac0c33Sjakob 			int val = (hexdigit_to_int(s[1]) * 100 +
38462ac0c33Sjakob 				   hexdigit_to_int(s[2]) * 10 +
38562ac0c33Sjakob 				   hexdigit_to_int(s[3]));
38662ac0c33Sjakob 			if (0 <= val && val <= 255) {
38762ac0c33Sjakob 				s += 3;
38862ac0c33Sjakob 				*p = val;
38962ac0c33Sjakob 			} else {
39062ac0c33Sjakob 				zc_warning("text escape \\DDD overflow");
39162ac0c33Sjakob 				*p = *++s;
39262ac0c33Sjakob 			}
39362ac0c33Sjakob 		} else if (s[1] != '\0') {
39462ac0c33Sjakob 			/* \X where X is any character, keep X.  */
39562ac0c33Sjakob 			*p = *++s;
39662ac0c33Sjakob 		} else {
39762ac0c33Sjakob 			/* Trailing backslash, ignore it.  */
39862ac0c33Sjakob 			zc_warning("trailing backslash ignored");
39962ac0c33Sjakob 			--p;
40062ac0c33Sjakob 		}
40162ac0c33Sjakob 	}
40262ac0c33Sjakob 	*p = '\0';
40362ac0c33Sjakob 	return p - text;
40462ac0c33Sjakob }
40562ac0c33Sjakob 
40662ac0c33Sjakob static int
40762ac0c33Sjakob parse_token(int token, char *yytext, enum lexer_state *lexer_state)
40862ac0c33Sjakob {
409a8b34139Sjakob 	size_t len;
410a8b34139Sjakob 	char *str;
41162ac0c33Sjakob 
41262ac0c33Sjakob 	if (*lexer_state == EXPECT_OWNER) {
41362ac0c33Sjakob 		*lexer_state = PARSING_OWNER;
41462ac0c33Sjakob 	} else if (*lexer_state == PARSING_TTL_CLASS_TYPE) {
41562ac0c33Sjakob 		const char *t;
41662ac0c33Sjakob 		int token;
41762ac0c33Sjakob 		uint16_t rrclass;
41862ac0c33Sjakob 
41962ac0c33Sjakob 		/* type */
420a8b34139Sjakob 		token = rrtype_to_token(yytext, &yylval.type);
42162ac0c33Sjakob 		if (token != 0) {
42262ac0c33Sjakob 			*lexer_state = PARSING_RDATA;
42362ac0c33Sjakob 			LEXOUT(("%d[%s] ", token, yytext));
42462ac0c33Sjakob 			return token;
42562ac0c33Sjakob 		}
42662ac0c33Sjakob 
42762ac0c33Sjakob 		/* class */
428a8b34139Sjakob 		rrclass = rrclass_from_string(yytext);
42962ac0c33Sjakob 		if (rrclass != 0) {
43062ac0c33Sjakob 			yylval.klass = rrclass;
43162ac0c33Sjakob 			LEXOUT(("CLASS "));
43262ac0c33Sjakob 			return T_RRCLASS;
43362ac0c33Sjakob 		}
43462ac0c33Sjakob 
43562ac0c33Sjakob 		/* ttl */
436a8b34139Sjakob 		yylval.ttl = strtottl(yytext, &t);
43762ac0c33Sjakob 		if (*t == '\0') {
43862ac0c33Sjakob 			LEXOUT(("TTL "));
43962ac0c33Sjakob 			return T_TTL;
44062ac0c33Sjakob 		}
44162ac0c33Sjakob 	}
44262ac0c33Sjakob 
443a8b34139Sjakob 	str = region_strdup(parser->rr_region, yytext);
444a8b34139Sjakob 	len = zoctet(str);
445a8b34139Sjakob 
44662ac0c33Sjakob 	yylval.data.str = str;
44762ac0c33Sjakob 	yylval.data.len = len;
44862ac0c33Sjakob 
44962ac0c33Sjakob 	LEXOUT(("%d[%s] ", token, yytext));
45062ac0c33Sjakob 	return token;
45162ac0c33Sjakob }
452