fxsdk/fxos/lexer-reg.l
Lephe 25db504c22 fxos: bring disassembling to a new level
Almost-complete implementation of fxos, the disassembler in particular
is now able to detect syscalls and register addresses on the fly, plus
support for SH4-only instructions.
2019-05-03 11:19:36 +02:00

117 lines
2 KiB
Text

%{
#include <fxos.h>
#include <errors.h>
#include <util.h>
/* Values for tokens generated by the lexer */
static union {
char *text;
long long integer;
} yylval;
/* Token list */
#define NUMBER 0
#define SYMBOL 1
%}
%option prefix="reg"
%option noyywrap
%option nounput
decimal 0|[1-9][0-9]*
octal 0[0-7]+
hexa 0x[0-9a-fA-F]+
number {decimal}|{octal}|{hexa}
symbol [^0-9 \t\n][^\n]*
space [ \t]+
%%
^#[^\n]* ;
{space} ;
[\n] yylineno++;
{number} { yylval.integer = integer(yytext, NULL); return NUMBER; }
{symbol} { yylval.text = strdup(yytext); return SYMBOL; }
<<EOF>> return -1;
%%
#include <stdio.h>
/* lex_reg(): Peripheral register table lexer and parser */
struct reg_address *lex_reg(void *data, size_t len, int *count)
{
/* Count number of register descriptions (upper bound) */
YY_BUFFER_STATE buf = yy_scan_bytes(data, len);
yylineno = 1;
int total = 0, t;
while((t = yylex()) != -1)
{
total += (t == NUMBER);
if(t == SYMBOL) free(yylval.text);
}
yy_delete_buffer(buf);
/* Allocate a large enough register array */
struct reg_address *table = calloc(total, sizeof *table);
if(!table)
{
errf(ERR_ERRNO, "cannot allocate memory for database");
return 0;
}
/* Lex all instructions and fill in the array */
buf = yy_scan_bytes(data, len);
yylineno = 1;
struct reg_address *reg = table - 1;
int line = -1;
while(1)
{
t = yylex();
if(t == NUMBER || t == -1)
{
/* Finalize current instruction */
if(reg >= table && !reg->name)
err("%d: unnamed register", line);
else reg++;
}
if(t == -1) break;
if(t == NUMBER)
{
reg->address = yylval.integer;
line = yylineno;
}
else if(t == SYMBOL && reg < table)
{
err("%d: expected register address", yylineno);
free(yylval.text);
}
else if(t == SYMBOL && !reg->name)
{
reg->name = yylval.text;
}
else if(t == SYMBOL)
{
err("%d: excess names for 0x%08x\n", reg->address);
free(yylval.text);
}
}
yy_delete_buffer(buf);
if(count) *count = reg - table;
return table;
}