mirror of
https://github.com/ksherlock/mpw.git
synced 2025-01-09 13:30:34 +00:00
apply template
This commit is contained in:
parent
d400bfb4da
commit
8e434d39f8
@ -71,7 +71,8 @@ set_source_files_properties(
|
||||
add_executable(mpw loader.cpp debugger.cpp debugger_internal.cpp
|
||||
address_map.cpp lexer.cpp parser.cpp loadtrap.cpp
|
||||
commands.cpp
|
||||
template_loader.cpp template_parser.cpp)
|
||||
template_loader.cpp template_parser.cpp intern.cpp template.cpp)
|
||||
|
||||
|
||||
target_link_libraries(mpw CPU_LIB)
|
||||
target_link_libraries(mpw TOOLBOX_LIB)
|
||||
|
@ -1136,8 +1136,24 @@ void Info(uint32_t address)
|
||||
cp = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ApplyTemplate(int32_t address, const std::string &name)
|
||||
{
|
||||
// find the template..
|
||||
|
||||
auto iter = TemplateTable.find(name);
|
||||
if (iter == TemplateTable.end()) {
|
||||
fprintf(stderr, "Unknown template: %s\n", name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
FieldEntry *e = iter->second;
|
||||
ApplyTemplate(address, e);
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
|
@ -144,6 +144,8 @@ void ReadWriteBreak(int32_t address);
|
||||
void PrintError(uint32_t value);
|
||||
void PrintDate(uint32_t value);
|
||||
|
||||
void ApplyTemplate(int32_t address, const std::string &name);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
20
bin/lexer.rl
20
bin/lexer.rl
@ -105,6 +105,21 @@ namespace {
|
||||
# this exits with cs == lexer_en_error.
|
||||
error := any* ${ fbreak; };
|
||||
|
||||
# identifiers.
|
||||
ident := |*
|
||||
|
||||
[ \t\r\n]+;
|
||||
|
||||
[_A-Za-z][_A-Za-z0-9]* {
|
||||
|
||||
std::unique_ptr<std::string> sp(new std::string(ts, te));
|
||||
|
||||
Parse(parser, tkIDENTIFIER, Token::Make(sp.get(), 0), command);
|
||||
Strings.push_back(std::move(sp));
|
||||
};
|
||||
|
||||
*|;
|
||||
|
||||
# semi-colon commands.
|
||||
semi := |*
|
||||
|
||||
@ -130,7 +145,10 @@ namespace {
|
||||
Parse(parser, tkSEMIERROR, 0, command);
|
||||
};
|
||||
|
||||
|
||||
't'i {
|
||||
Parse(parser, tkSEMIT, 0, command);
|
||||
fgoto ident;
|
||||
};
|
||||
|
||||
*|;
|
||||
|
||||
|
@ -200,7 +200,6 @@ stmt ::= expr(a) COLON expr(b) SEMI SEMIL EOL.
|
||||
Debug::List(a.intValue, b.intValue);
|
||||
}
|
||||
|
||||
|
||||
stmt ::= expr(a) SEMI SEMIDATE EOL.
|
||||
{
|
||||
Debug::PrintDate(a.intValue);
|
||||
@ -212,6 +211,11 @@ stmt ::= expr(a) SEMI SEMIERROR EOL.
|
||||
Debug::PrintError(a.intValue);
|
||||
}
|
||||
|
||||
stmt ::= expr(a) SEMI SEMIT IDENTIFIER(b) EOL.
|
||||
{
|
||||
Debug::ApplyTemplate(a.intValue, *b.stringValue);
|
||||
}
|
||||
|
||||
|
||||
stmt ::= DREGISTER(a) EQ expr(b) EOL.
|
||||
{
|
||||
|
224
bin/template.cpp
Normal file
224
bin/template.cpp
Normal file
@ -0,0 +1,224 @@
|
||||
#include "template.h"
|
||||
#include "debugger.h"
|
||||
|
||||
namespace Debug {
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
unsigned CalcOneSize(FieldEntry *e)
|
||||
{
|
||||
unsigned s = (e->type & 0x0f00) >> 8;
|
||||
|
||||
if (!s) {
|
||||
// struct or pointer...
|
||||
if (e->type & 0x8000) s = 4;
|
||||
else if (e->tmpl) s = e->tmpl->struct_size;
|
||||
}
|
||||
|
||||
if (e->count) s *= e->count;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
unsigned CalcSize(FieldEntry *e)
|
||||
{
|
||||
unsigned size = 0;
|
||||
|
||||
while (e)
|
||||
{
|
||||
size += CalcOneSize(e);
|
||||
e = e->next;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
FieldEntry *Reverse(FieldEntry *e)
|
||||
{
|
||||
if (!e) return e;
|
||||
|
||||
// reverse the order...
|
||||
FieldEntry *prev;
|
||||
FieldEntry *next;
|
||||
|
||||
prev = nullptr;
|
||||
for(;;)
|
||||
{
|
||||
next = e->next;
|
||||
e->next = prev;
|
||||
|
||||
prev = e;
|
||||
e = next;
|
||||
if (!e) return prev;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CreateTypedef(const std::string *name, int type, TemplateParseInfo *info)
|
||||
{
|
||||
// check if it's an existing typedef...
|
||||
|
||||
auto &Templates = *info->templates;
|
||||
auto &Types = *info->types;
|
||||
|
||||
|
||||
auto iter = Types.find(*name);
|
||||
if (iter != Types.end())
|
||||
{
|
||||
if (iter->second == type) return; // ok, just a duplicate.
|
||||
fprintf(stderr, "Template Error: line %d - redefining %s\n",
|
||||
info->LineNumber, name->c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Templates.find(*name) != Templates.end())
|
||||
{
|
||||
fprintf(stderr, "Template Error: line %d - redefining %s\n",
|
||||
info->LineNumber, name->c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Types.emplace(std::make_pair(*name, type));
|
||||
}
|
||||
|
||||
|
||||
void CreateTemplate(const std::string *name, FieldEntry *firstField, TemplateParseInfo *info)
|
||||
{
|
||||
auto &Templates = *info->templates;
|
||||
auto &Types = *info->types;
|
||||
|
||||
// check if it exists...
|
||||
|
||||
if (Templates.find(*name) != Templates.end())
|
||||
{
|
||||
fprintf(stderr, "Template Error: line %d - redefining %s\n",
|
||||
info->LineNumber, name->c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (Types.find(*name) != Types.end())
|
||||
{
|
||||
fprintf(stderr, "Template Error: line %d - redefining %s\n",
|
||||
info->LineNumber, name->c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
firstField = Reverse(firstField);
|
||||
firstField->struct_size = CalcSize(firstField);
|
||||
|
||||
Templates.emplace(std::make_pair(*name, firstField));
|
||||
}
|
||||
|
||||
|
||||
void PrettyPrint(uint32_t value, unsigned type)
|
||||
{
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case kOSType:
|
||||
// print 4-cc code
|
||||
return;
|
||||
case kOSErr:
|
||||
// print value + short name
|
||||
return;
|
||||
|
||||
case kPStringPtr:
|
||||
// read the string...
|
||||
return;
|
||||
|
||||
case kCStringPtr:
|
||||
// read the string...
|
||||
return;
|
||||
|
||||
case kBoolean:
|
||||
fputs(value ? "true" : "false", stdout);
|
||||
return;
|
||||
|
||||
case kHandle:
|
||||
// print address, size, locked stats.
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// int/signed int - print base 10.
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ApplyTemplate(uint32_t address, FieldEntry *e, unsigned indent)
|
||||
{
|
||||
unsigned offset = 0;
|
||||
|
||||
for( ; e ; e = e->next)
|
||||
{
|
||||
|
||||
unsigned count = e->count;
|
||||
unsigned type = e->type;
|
||||
unsigned s = (type & 0x0f00) >> 8;
|
||||
|
||||
if (!s) {
|
||||
// struct or pointer...
|
||||
if (e->type & 0x8000) s = 4;
|
||||
else if (e->tmpl) s = e->tmpl->struct_size;
|
||||
}
|
||||
|
||||
|
||||
printf("%-20s", e->name->c_str());
|
||||
|
||||
// todo -- support arrays
|
||||
// todo -- pretty print values (boolean, oserr, ostype, etc.)
|
||||
switch(s)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
uint8_t value = ReadByte(address + offset);
|
||||
printf(" %02x", value);
|
||||
PrettyPrint(value, type);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
uint16_t value = ReadWord(address + offset);
|
||||
printf(" %04x", value);
|
||||
PrettyPrint(value, type);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
uint32_t value = ReadLong(address + offset);
|
||||
printf("%08x", value);
|
||||
PrettyPrint(value, type);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0:
|
||||
// either a pointer or a struct
|
||||
if (type & 0x8000) {
|
||||
// pointer.
|
||||
uint32_t value = ReadLong(address + offset);
|
||||
printf("%08x", value);
|
||||
PrettyPrint(value, type);
|
||||
break;
|
||||
}
|
||||
if (type == 0) {
|
||||
// struct ... recurse.
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
offset += CalcOneSize(e);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
#define __debug_template_h__
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
namespace Debug {
|
||||
|
||||
@ -128,6 +129,9 @@ namespace Debug {
|
||||
bool LoadTemplateFile(const std::string &filename, std::unordered_map<std::string, Template> &);
|
||||
|
||||
|
||||
void ApplyTemplate(uint32_t address, FieldEntry *e, unsigned indent = 0);
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -50,7 +50,7 @@ void TemplateParse(void *yyp, int yymajor, void *yyminor, Debug::TemplateParseIn
|
||||
|
||||
void TemplateParse(void *yyp, int yymajor, int yyminor, Debug::TemplateParseInfo *info)
|
||||
{
|
||||
TemplateParse(yyp, yymajor, (void *)yyminor, info);
|
||||
TemplateParse(yyp, yymajor, (void *)(ptrdiff_t)yyminor, info);
|
||||
}
|
||||
|
||||
void TemplateParse(void *yyp, int yymajor, const std::string *yyminor, Debug::TemplateParseInfo *info)
|
||||
@ -175,104 +175,7 @@ void TemplateParse(void *yyp, int yymajor, const std::string *yyminor, Debug::Te
|
||||
namespace Debug {
|
||||
|
||||
|
||||
void CreateTypedef(const std::string *name, int type, TemplateParseInfo *info)
|
||||
{
|
||||
// check if it's an existing typedef...
|
||||
|
||||
auto &Templates = *info->templates;
|
||||
auto &Types = *info->types;
|
||||
|
||||
|
||||
auto iter = Types.find(*name);
|
||||
if (iter != Types.end())
|
||||
{
|
||||
if (iter->second == type) return; // ok, just a duplicate.
|
||||
fprintf(stderr, "Template Error: line %d - redefining %s\n",
|
||||
info->LineNumber, name->c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Templates.find(*name) != Templates.end())
|
||||
{
|
||||
fprintf(stderr, "Template Error: line %d - redefining %s\n",
|
||||
info->LineNumber, name->c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Types.emplace(std::make_pair(*name, type));
|
||||
}
|
||||
|
||||
unsigned CalcSize(FieldEntry *e)
|
||||
{
|
||||
unsigned size = 0;
|
||||
|
||||
while (e)
|
||||
{
|
||||
unsigned s = (e->type & 0x0f00) >> 8;
|
||||
|
||||
if (!s) {
|
||||
// struct or pointer...
|
||||
if (e->type & 0x8000) s = 4;
|
||||
else if (e->tmpl) s = e->tmpl->struct_size;
|
||||
}
|
||||
|
||||
if (e->count != 0) s *= e->count;
|
||||
|
||||
size += s;
|
||||
e = e->next;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
FieldEntry *Reverse(FieldEntry *e)
|
||||
{
|
||||
if (!e) return e;
|
||||
|
||||
// reverse the order...
|
||||
FieldEntry *prev;
|
||||
FieldEntry *next;
|
||||
|
||||
prev = nullptr;
|
||||
for(;;)
|
||||
{
|
||||
next = e->next;
|
||||
e->next = prev;
|
||||
|
||||
prev = e;
|
||||
e = next;
|
||||
if (!e) return prev;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CreateTemplate(const std::string *name, FieldEntry *firstField, TemplateParseInfo *info)
|
||||
{
|
||||
auto &Templates = *info->templates;
|
||||
auto &Types = *info->types;
|
||||
|
||||
// check if it exists...
|
||||
|
||||
if (Templates.find(*name) != Templates.end())
|
||||
{
|
||||
fprintf(stderr, "Template Error: line %d - redefining %s\n",
|
||||
info->LineNumber, name->c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (Types.find(*name) != Types.end())
|
||||
{
|
||||
fprintf(stderr, "Template Error: line %d - redefining %s\n",
|
||||
info->LineNumber, name->c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
firstField = Reverse(firstField);
|
||||
firstField->struct_size = CalcSize(firstField);
|
||||
|
||||
Templates.emplace(std::make_pair(*name, firstField));
|
||||
}
|
||||
|
||||
|
||||
bool LoadTemplateFile(const std::string &filename, std::unordered_map<std::string, Template> &Templates)
|
||||
|
Loading…
Reference in New Issue
Block a user