mpw/bin/template.cpp

273 lines
5.1 KiB
C++

#include "template.h"
#include "debugger.h"
#include "debugger_internal.h"
#include "loader.h" // Flags.
#include <algorithm>
#include <toolbox/toolbox.h>
namespace Debug {
using namespace Debug::Internal;
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;
}
}
inline bool ValidPointer(uint32_t value)
{
return value && value < Flags.memorySize;
}
}
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 CleanupString(std::string &s)
{
// replace non-printables.
std::transform(s.begin(), s.end(), s.begin(), [](char c){
return isprint(c) ? c : '.';
});
if (s.size() > 40) {
s.resize(37);
s.append("...");
}
}
void PrettyPrint(uint32_t value, unsigned type)
{
switch (type)
{
case kOSType:
// print 4-cc code
fputc(' ', stdout);
fputs(ToolBox::TypeToString(value).c_str(), stdout);
return;
case kOSErr:
// print value + short name
{
printf(" %-6d", (int16_t)value);
auto iter = ErrorTableInvert.find(value);
if (iter != ErrorTableInvert.end()) printf(" %s", iter->second.c_str());
}
return;
case kPStringPtr:
// read the string...
if (ValidPointer(value))
{
std::string tmp = ReadPString(value);
CleanupString(tmp);
printf(" '%s'", tmp.c_str());
}
return;
case kCStringPtr:
// read the string...
if (ValidPointer(value))
{
std::string tmp = ReadCString(value);
CleanupString(tmp);
printf(" '%s'", tmp.c_str());
}
return;
return;
case kBoolean:
fputc(' ', stdout);
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;
if (!e) return;
for( ; e ; e = e->next)
{
bool nonl = false;
unsigned count = e->count;
unsigned type = e->type;
unsigned s = (type & 0x0f00) >> 8;
for (unsigned i = 0; i < indent; ++i) fputc('>',stdout);
printf("%08x %s", address + offset, e->name->c_str());
for(unsigned i = indent + e->name->length(); i < 32; ++i) fputc(' ',stdout);
// 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.
fputc('\n', stdout);
nonl = true;
ApplyTemplate(address + offset, e->tmpl, indent + 1);
break;
}
}
if (!nonl) fputc('\n', stdout);
offset += CalcOneSize(e);
}
}
}