%{
#include "disasm.h"
#include "disasm-opt.gperf.h"

YY_BUFFER_STATE fstack[10];
int fstack_ptr = 0;

char buf[256];
char *buf_ptr;

int lineno;
%}

ID		[a-zA-Z_][a-zA-Z0-9_]*

%x comment
%x str
%x incl

%option nounput
%option noyywrap

%%

[ \t]+		/* eat */
\n		lineno++;

include		BEGIN (incl);
<incl>[ \t]*	/* eat */
<incl>\"[^\"\n]+\"	{
				strncpy (buf, opttext + 1, optleng);
				buf[optleng - 2] = 0;
				fstack[fstack_ptr++] = YY_CURRENT_BUFFER;
				optin = fopen (buf, "r");
				opt_switch_to_buffer (opt_create_buffer (optin, YY_BUF_SIZE));
				BEGIN (INITIAL);
			}
<incl>\n	BEGIN (INITIAL);

<<EOF>>		{
			if (!fstack_ptr)
				yyterminate ();
			else
			{
				opt_delete_buffer (YY_CURRENT_BUFFER);
				opt_switch_to_buffer (fstack[--fstack_ptr]);
				BEGIN (incl);
			}
			break;
		}

#		BEGIN(comment);
<comment>[^\n]	/* eat */
<comment>\n	BEGIN(INITIAL);

[0-9]+		{ optlval.num = strtoul (opttext, NULL, 0); return NUM; }
0x[0-9a-fA-F]+	{ optlval.num = strtoul (opttext+2, NULL, 16); return NUM; }

{ID}		{
			const struct disasmopt_keywords *k;
			struct symbol *s;
			
			if ((k = disasm_opt_lookup (opttext, strlen (opttext))))
				return k->symbol;
			for (s = first_sym; s != NULL; s = s->next)
				if (!strcmp (s->name, opttext))
				{
					optlval.symbol = s;
					return SYMBOL;
				}
			strncpy (buf, opttext, optleng);
			buf[optleng] = 0;
			optlval.string = buf;
			return IDENT;
		}

\"		{ buf_ptr = buf; BEGIN (str); }
<str>\\t	{ *buf_ptr = '\t'; }
<str>\\n	{ *buf_ptr = '\n'; }
<str>\\.	{ *buf_ptr = opttext[1]; }
<str>[^\\\"\n]+	{ strcpy (buf_ptr, opttext); buf_ptr += strlen (buf_ptr); }
<str>\"		{ *buf_ptr = 0; optlval.string = buf; BEGIN (INITIAL); return STRING; }

.		return opttext[0];

%%

/* End of file. */
