%{ #include #include #include #include #include #include #include /* Tokens */ #define NAME 0 #define ADDRESS 1 #define SIZE 2 #define PATH 3 /* Value for parser */ static union { char *name; uint32_t address; uint32_t size; char *path; } yylval; /* Current file name */ static std::string filename; /* Error messages and exceptions */ __attribute__((noreturn)) 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="target" %option noyywrap %option nounput name [a-zA-Z_][a-zA-Z0-9_]* hexa [0-9a-fA-F]+ path [^: \t\n]+$ space [ \t]+ %% ^#[^\n]* ; {space} ; [\n] yylineno++; {hexa} { sscanf(yytext, "%x", &yylval.address); return ADDRESS; } "("{hexa}")" { sscanf(yytext, "(%x)", &yylval.size); return SIZE; } {name} { yylval.name = strdup(yytext); return NAME; } ":" { return ':'; } {path} { yylval.path = strdup(yytext); return PATH; } . { err("lex error near '%s'", yytext); } <> { return -1; } %% namespace FxOS { static int expect(std::vector types) { std::array description { "region name", "address", "size", "file path" }; int t = yylex(); for(int allowed: types) if(t == allowed) return t; std::string errmsg = "expected"; for(int allowed: types) { if(allowed >= 0 && allowed < (int)description.size()) { errmsg += " "; errmsg += description[t]; errmsg += ","; } else if(allowed == -1) { errmsg += " end of file,"; } else if(allowed == ':') { errmsg += " colon,"; } } err(errmsg.c_str()); } static int expect(int type) { std::vector types { type }; return expect(types); } /* Load a target description into the target database. */ TargetDescription load_target(Buffer const &file, size_t offset, size_t line) { /* Build a target description without actually loading the files. */ TargetDescription descr; YY_BUFFER_STATE buf = yy_scan_bytes(file.data.get() + offset, file.size - offset); yylineno = line; filename = file.path; while(1) { MemoryRegion reg; /* One iteration per line */ int t = expect({ NAME, ADDRESS, -1 }); if(t == -1) break; if(t == NAME) { reg = MemoryRegion(yylval.name); free(yylval.name); } else if(t == ADDRESS) { uint32_t start = yylval.address; expect(SIZE); uint32_t size = yylval.size; reg = MemoryRegion("(anonymous)", start, start + size, true); } expect(':'); expect(PATH); std::string path = yylval.path; free(yylval.path); TargetDescription::Binding b = std::make_pair(reg, path); descr.bindings.push_back(b); } yy_delete_buffer(buf); return descr; } } /* namespace FxOS */