mirror of
https://github.com/ksherlock/mpw.git
synced 2024-11-22 15:31:50 +00:00
load trap - process entire (mapped) file with one-shot.
This commit is contained in:
parent
c8ea11f1b0
commit
e0b6ba2c31
332
bin/loadtrap.rl
332
bin/loadtrap.rl
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, Kelvin W Sherlock
|
* Copyright (c) 2013, 2016, Kelvin W Sherlock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -24,261 +24,121 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <map>
|
%%{
|
||||||
#include <string>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
machine load_traps;
|
||||||
#include <limits.h>
|
alphtype unsigned char;
|
||||||
|
|
||||||
namespace _loadtrap_rl {
|
action reset {
|
||||||
#if __APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
|
negative = false;
|
||||||
#define _GETDELIM_GROWBY 128 /* amount to grow line buffer by */
|
value = 0;
|
||||||
#define _GETDELIM_MINLEN 4 /* minimum line buffer size */
|
key.clear();
|
||||||
|
scratch.clear();
|
||||||
ssize_t getdelim(char ** lineptr, size_t * n, int delimiter, FILE * stream) {
|
|
||||||
char *buf, *pos;
|
|
||||||
int c;
|
|
||||||
ssize_t bytes;
|
|
||||||
|
|
||||||
if (lineptr == NULL || n == NULL) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (stream == NULL) {
|
|
||||||
errno = EBADF;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* resize (or allocate) the line buffer if necessary */
|
|
||||||
buf = *lineptr;
|
|
||||||
if (buf == NULL || *n < _GETDELIM_MINLEN) {
|
|
||||||
buf = (char*)realloc(*lineptr, _GETDELIM_GROWBY);
|
|
||||||
if (buf == NULL) {
|
|
||||||
/* ENOMEM */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*n = _GETDELIM_GROWBY;
|
|
||||||
*lineptr = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read characters until delimiter is found, end of file is reached, or an
|
|
||||||
error occurs. */
|
|
||||||
bytes = 0;
|
|
||||||
pos = buf;
|
|
||||||
while ((c = getc(stream)) != EOF) {
|
|
||||||
if (bytes + 1 >= SSIZE_MAX) {
|
|
||||||
errno = EOVERFLOW;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
bytes++;
|
|
||||||
if (bytes >= *n - 1) {
|
|
||||||
buf = (char*)realloc(*lineptr, *n + _GETDELIM_GROWBY);
|
|
||||||
if (buf == NULL) {
|
|
||||||
/* ENOMEM */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*n += _GETDELIM_GROWBY;
|
|
||||||
pos = buf + bytes - 1;
|
|
||||||
*lineptr = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pos++ = (char) c;
|
|
||||||
if (c == delimiter) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ferror(stream) || (feof(stream) && (bytes == 0))) {
|
|
||||||
/* EOF, or an error from getc(). */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pos = '\0';
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t getline(char ** lineptr, size_t * n, FILE * stream) {
|
|
||||||
#if __APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
|
|
||||||
return getdelim(lineptr, n, '\n', stream);
|
|
||||||
#else
|
|
||||||
return ::getline(lineptr, n, stream);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
namespace {
|
|
||||||
// private...
|
|
||||||
%%{
|
|
||||||
|
|
||||||
machine lexer;
|
|
||||||
|
|
||||||
action addx {
|
action commit {
|
||||||
int x = fc;
|
bool ok = true;
|
||||||
if (x >= '0' && x <= '9') x = x -'0';
|
|
||||||
else x = (x | 0x20) - 'a' + 10;
|
if (!scratch.empty()) {
|
||||||
value = (value << 4) + x;
|
auto iter = table.find(scratch);
|
||||||
|
if (iter == table.end()) {
|
||||||
|
fprintf(stderr, "Undefined reference: %s\n", scratch.c_str());
|
||||||
|
ok = false;
|
||||||
}
|
}
|
||||||
|
else value = iter->second;
|
||||||
ws = [ \t];
|
|
||||||
|
|
||||||
value =
|
|
||||||
'0x' xdigit+ @addx
|
|
||||||
|
|
|
||||||
'$' xdigit+ @addx
|
|
||||||
|
|
|
||||||
'-'? @{ negative = true; }
|
|
||||||
digit+ @{value = value * 10 + (fc - '0'); }
|
|
||||||
|
|
|
||||||
[A-Za-z_] @{ stringValue.push_back(fc); }
|
|
||||||
[A-Za-z0-9_]+ @{ stringValue.push_back(fc); }
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
name =
|
|
||||||
[A-Za-z0-9_]+ @{
|
|
||||||
name.push_back(fc);
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
main :=
|
|
||||||
|
|
||||||
name
|
|
||||||
ws*
|
|
||||||
'='
|
|
||||||
ws*
|
|
||||||
value
|
|
||||||
;
|
|
||||||
|
|
||||||
write data;
|
|
||||||
}%%
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool ParseLine(const char *p, const char *pe, std::map<std::string, uint16_t> &map)
|
|
||||||
{
|
|
||||||
|
|
||||||
// trap = number
|
|
||||||
// or trap = [previously defined trap]
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
std::string stringValue;
|
|
||||||
uint32_t value;
|
|
||||||
bool negative = false;
|
|
||||||
|
|
||||||
value = 0;
|
|
||||||
const char *eof = pe;
|
|
||||||
int cs;
|
|
||||||
|
|
||||||
%%write init;
|
|
||||||
%%write exec;
|
|
||||||
|
|
||||||
if (cs < %%{ write first_final; }%% )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (negative) value = (-value) & 0xffff;
|
|
||||||
|
|
||||||
// name lookup
|
|
||||||
if (!stringValue.empty())
|
|
||||||
{
|
|
||||||
auto iter = map.find(stringValue);
|
|
||||||
if (iter == map.end())
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Undefined trap: %s\n", stringValue.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
value = iter->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// if loading globals, wouldn't need to do this...
|
|
||||||
if (value > 0xafff || value < 0xa000)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Invalid trap number: $%04x\n", value);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
map.emplace(name, (uint16_t)value);
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (negative) value = -value;
|
||||||
|
|
||||||
|
if (ok) table.emplace(std::move(key), value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eol = [\r\n] ${ line++; };
|
||||||
|
ws = [ \t];
|
||||||
|
|
||||||
|
error := [^\r\n]* eol $reset ${ fnext main; };
|
||||||
|
|
||||||
|
comment = '#' [^\r\n]*;
|
||||||
|
|
||||||
|
|
||||||
|
word = [A-Za-z_][A-Za-z_0-9]*;
|
||||||
|
key = word ${ key.push_back(fc); };
|
||||||
|
|
||||||
|
base16 =
|
||||||
|
[0-9] ${value = (value << 4) + fc - '0'; }
|
||||||
|
| [A-Fa-f] ${value = (value << 4) + (fc | 0x20) - 'a' + 10; }
|
||||||
|
;
|
||||||
|
|
||||||
|
base10 = [0-9]+ ${ value = (value * 10) + fc - '0'; };
|
||||||
|
|
||||||
|
decnumber = ( '-' ${ negative = true; } )? base10+;
|
||||||
|
hexnumber = ('$' | '0x') base16+;
|
||||||
|
|
||||||
|
number = decnumber | hexnumber;
|
||||||
|
|
||||||
|
value = number | word ${ scratch.push_back(fc); };
|
||||||
|
|
||||||
|
|
||||||
|
line =
|
||||||
|
ws* ( key ws* '=' ws* value %commit %reset ws*)? comment? eol
|
||||||
|
;
|
||||||
|
|
||||||
|
main := line*
|
||||||
|
$err{
|
||||||
|
fprintf(stderr, "Unexpected character '%c' on line %d\n", fc, line);
|
||||||
|
fnext error;
|
||||||
|
};
|
||||||
|
|
||||||
|
}%%;
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
%% write data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cxx/mapped_file.h>
|
||||||
|
|
||||||
namespace Debug {
|
namespace Debug {
|
||||||
|
|
||||||
void LoadTrapFile(const std::string &path, std::map<std::string, uint16_t> &map)
|
void LoadTrapFile(const std::string &path, std::map<std::string, uint16_t> &table) {
|
||||||
{
|
int cs;
|
||||||
FILE *fp;
|
const unsigned char *p;
|
||||||
|
const unsigned char *pe;
|
||||||
|
const unsigned char *eof;
|
||||||
|
int line = 1;
|
||||||
|
|
||||||
fp = fopen(path.c_str(), "r");
|
int value = 0;
|
||||||
if (!fp)
|
bool negative = false;
|
||||||
{
|
std::string key;
|
||||||
fprintf(stderr, "Unable to open trap file %s\n", path.c_str());
|
std::string scratch;
|
||||||
|
|
||||||
|
mapped_file mf;
|
||||||
|
try {
|
||||||
|
mf.open(path, mapped_file::readonly);
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
//fprintf(stderr, "### %s: %s\n", path.c_str(), ex.what());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%% write init;
|
||||||
|
p = mf.cbegin();
|
||||||
|
pe = mf.cend();
|
||||||
|
eof = nullptr;
|
||||||
|
|
||||||
/*
|
for (int i = 0; i < 2; ++i) {
|
||||||
* getline(3) is 2008 posix. it allocates (and resizes as appropriate)
|
%% write exec;
|
||||||
* the buffer.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
char *lineBuffer = NULL;
|
|
||||||
size_t lineSize = 0;
|
|
||||||
|
|
||||||
for(;;)
|
p = (const unsigned char *)"\n";
|
||||||
{
|
pe = eof = p+1;
|
||||||
char *line;
|
|
||||||
ssize_t length;
|
|
||||||
|
|
||||||
length = _loadtrap_rl::getline(&lineBuffer, &lineSize, fp);
|
|
||||||
if (!length) continue; //?
|
|
||||||
if (length < 0) break; // eof or error.
|
|
||||||
|
|
||||||
line = lineBuffer;
|
|
||||||
|
|
||||||
// skip any leading space.
|
|
||||||
while (length && isspace(*line))
|
|
||||||
{
|
|
||||||
++line;
|
|
||||||
--length;
|
|
||||||
}
|
|
||||||
if (!length) continue;
|
|
||||||
|
|
||||||
// comments
|
|
||||||
if (*line == '#') continue;
|
|
||||||
|
|
||||||
|
|
||||||
// strip any trailing space.
|
|
||||||
// (will be \n terminated unless there was no \n)
|
|
||||||
while (length && isspace(line[length - 1]))
|
|
||||||
{
|
|
||||||
line[--length] = 0;
|
|
||||||
}
|
|
||||||
if (!length) continue;
|
|
||||||
|
|
||||||
if (!ParseLine(line, line + length, map))
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Error in trap definition: %s\n", line);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
@ -289,7 +149,7 @@ int main(int argc, char **argv)
|
|||||||
std::map<std::string, uint16_t> map;
|
std::map<std::string, uint16_t> map;
|
||||||
Debug::LoadTrapFile(f, map);
|
Debug::LoadTrapFile(f, map);
|
||||||
|
|
||||||
for(const auto kv : map)
|
for(const auto &kv : map)
|
||||||
{
|
{
|
||||||
printf("%s -> %04x\n", kv.first.c_str(), kv.second);
|
printf("%s -> %04x\n", kv.first.c_str(), kv.second);
|
||||||
}
|
}
|
||||||
@ -298,4 +158,4 @@ int main(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user