fxos/lib/load-symbols.l

115 lines
2.0 KiB
Plaintext

%{
#include <fxos/symbols.h>
#include <fxos/errors.h>
#include <fxos/util.h>
#include <fxos/load.h>
#include <cstdarg>
/* Text value and integer value for parser */
static char *yylval;
uint32_t yyival;
/* Tokens */
#define SYSCALL 1
#define ADDRESS 2
#define NAME 3
/* Current file name */
static std::string filename;
/* Error messages and exceptions */
static void err(char const *format, ...)
{
static char buf[256];
va_list args;
va_start(args, format);
vsnprintf(buf, 256, format, args);
va_end(args);
throw FxOS::SyntaxError(filename.c_str(), yylineno, buf);
}
%}
%option prefix="symbols"
%option noyywrap
%option nounput
syscall ^%[0-9A-Fa-f]{3,}
address ^[0-9A-Fa-f]{8}
name [a-zA-Z_][a-zA-Z_0-9.]*
space [ \t]+
%%
^#[^\n]* ;
{space} ;
[\n] yylineno++;
{syscall} { yyival = strtol(yytext+1, NULL, 16); return SYSCALL; }
{address} { yyival = strtol(yytext, NULL, 16); return ADDRESS; }
{name} { yylval = strdup(yytext); return NAME; }
. { err("lex error near '%s'", yytext); }
<<EOF>> { return -1; }
%%
namespace FxOS {
/* Load a symbol table into the disassembler */
SymbolTable load_symbols(Buffer const &file, size_t start_offset,
size_t start_line)
{
YY_BUFFER_STATE buf = yy_scan_bytes(file.data.get() + start_offset,
file.size - start_offset);
yylineno = start_line;
filename = file.path;
SymbolTable table;
/* Current symbol and line */
Symbol symbol;
int line = -1;
while(1)
{
int t = yylex();
if(line >= 0 && (yylineno != line || t != NAME || t == -1))
{
/* Finalize current symbol */
if(symbol.name == "") err("%d: missing name", line);
else table.add(symbol);
symbol = Symbol();
}
if(t == -1) break;
if(t == SYSCALL)
{
symbol.type = Symbol::Syscall;
symbol.value = yyival;
line = yylineno;
}
else if(t == ADDRESS)
{
symbol.type = Symbol::Address;
symbol.value = yyival;
line = yylineno;
}
else if(t == NAME)
{
symbol.name = yylval;
free(yylval);
}
}
yy_delete_buffer(buf);
return table;
}
} /* namespace FxOS */