mirror of
https://git.planet-casio.com/Lephenixnoir/fxsdk.git
synced 2024-12-29 13:03:37 +01:00
25db504c22
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.
123 lines
2.1 KiB
Text
123 lines
2.1 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 TEXT 1
|
|
|
|
%}
|
|
|
|
%option prefix="sys"
|
|
%option noyywrap
|
|
%option nounput
|
|
|
|
decimal 0|[1-9][0-9]*
|
|
octal 0[0-7]+
|
|
hexa 0x[0-9a-fA-F]+
|
|
number {decimal}|{octal}|{hexa}
|
|
|
|
space [ \t]+
|
|
|
|
%%
|
|
|
|
^#[^\n]* ;
|
|
{space} ;
|
|
[\n] yylineno++;
|
|
|
|
{number} { yylval.integer = integer(yytext, NULL); return NUMBER; }
|
|
[^ \t\n0-9].* { yylval.text = strdup(yytext); return TEXT; }
|
|
|
|
<<EOF>> return -1;
|
|
|
|
%%
|
|
|
|
#include <stdio.h>
|
|
|
|
/* lex_sys(): Syscall table lexer and parser */
|
|
struct sys_call *lex_sys(void *data, size_t len, int *count)
|
|
{
|
|
/* Count the number of syscalls */
|
|
|
|
YY_BUFFER_STATE buf = yy_scan_bytes(data, len);
|
|
yylineno = 1;
|
|
|
|
int total = 0, t;
|
|
while((t = yylex()) != -1)
|
|
{
|
|
total += (t == NUMBER);
|
|
if(t == TEXT) free(yylval.text);
|
|
}
|
|
|
|
yy_delete_buffer(buf);
|
|
|
|
/* Allocate a large enough syscall array */
|
|
|
|
struct sys_call *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 sys_call *call = table - 1;
|
|
int line = -1;
|
|
int named = 1;
|
|
|
|
while(1)
|
|
{
|
|
t = yylex();
|
|
|
|
if(t == NUMBER || t == -1)
|
|
{
|
|
/* Finalize current instruction */
|
|
if(!named) err("%d: unnamed syscall", line);
|
|
else call++;
|
|
}
|
|
if(t == -1) break;
|
|
|
|
if(t == NUMBER)
|
|
{
|
|
call->number = yylval.integer;
|
|
line = yylineno;
|
|
named = 0;
|
|
}
|
|
else if(t == TEXT && call < table)
|
|
{
|
|
err("%d: expected syscall id", yylineno);
|
|
free(yylval.text);
|
|
}
|
|
else if(t == TEXT && named == 0)
|
|
{
|
|
call->name = yylval.text;
|
|
named = 1;
|
|
}
|
|
else if(t == TEXT && named == 1)
|
|
{
|
|
call->descr = yylval.text;
|
|
named = 2;
|
|
}
|
|
else if(t == TEXT)
|
|
{
|
|
err("%d: excess qualifiers for syscall 0x%03x", line,
|
|
call->number);
|
|
free(yylval.text);
|
|
}
|
|
}
|
|
|
|
yy_delete_buffer(buf);
|
|
if(count) *count = call - table;
|
|
return table;
|
|
}
|