more template code

This commit is contained in:
Kelvin Sherlock 2014-12-29 15:15:34 -05:00
parent 7691267dea
commit 1cd59d36f3
6 changed files with 416 additions and 121 deletions

View File

@ -49,6 +49,7 @@
#include "debugger.h"
#include "debugger_internal.h"
#include "template.h"
#include <cpu/defs.h>
#include <cpu/CpuModule.h>
@ -62,8 +63,6 @@
#include <toolbox/loader.h>
#include <toolbox/mm.h>
namespace {
using namespace Debug::Internal;
@ -84,6 +83,8 @@ namespace {
ToolMap tbrkMap; // tool breaks.
std::unordered_map<std::string, Debug::Template> TemplateTable;
struct BackTraceInfo {
uint32_t a[8];
uint32_t d[8];
@ -1255,6 +1256,9 @@ void Shell()
LoadTrapFile(MPW::RootDirPathForFile("Globals.text"), GlobalTable);
LoadTrapFile(MPW::RootDirPathForFile("Traps.text"), TrapTable);
LoadTemplateFile(MPW::RootDirPathForFile("Templates.text"), TemplateTable);
// load the error code to error mnemonic
ErrorTableInvert.reserve(ErrorTable.size());

101
bin/intern.cpp Normal file
View File

@ -0,0 +1,101 @@
#include "intern.h"
#include <unordered_map>
namespace {
std::unordered_multimap<unsigned, std::string *> InternTable;
std::string EmptyString;
unsigned int DJBHash(const char* begin, size_t length)
{
unsigned int hash = 5381;
for(size_t i = 0; i < length; ++i)
{
hash = ((hash << 5) + hash) + (begin[i]);
}
return hash;
}
}
namespace Intern {
const std::string *String(std::string &&str)
{
size_t size = str.size();
if (!size) return &EmptyString;
unsigned hash = DJBHash(str.data(), size);
auto range = InternTable.equal_range(hash);
auto iter = range.first;
auto endit = range.second;
for( ; iter != endit; ++iter)
{
// hash matches, make sure the string does.
const std::string *s = iter->second;
if (s->size() == size && std::memcmp(s->data(), str.data(), size) == 0)
return s;
}
// insert it. I suppose this could throw, in which case a string would leak.
std::string *s = new std::string(std::move(str));
InternTable.emplace(std::make_pair(hash, s));
return s;
}
const std::string *String(const char *begin, size_t size)
{
if (!size) return &EmptyString;
unsigned hash = DJBHash(begin, size);
auto range = InternTable.equal_range(hash);
auto iter = range.first;
auto endit = range.second;
for( ; iter != endit; ++iter)
{
// hash matches, make sure the string does.
const std::string *s = iter->second;
if (s->size() == size && std::memcmp(s->data(), begin, size) == 0)
return s;
}
// insert it. I suppose this could throw, in which case a string would leak.
std::string *s = new std::string(begin, size);
InternTable.emplace(std::make_pair(hash, s));
return s;
}
const std::string *String(const char *begin, const char *end)
{
return String(begin, end - begin);
}
const std::string *String(const char *cp)
{
if (!cp || !*cp) return &EmptyString;
return String(cp, strlen(cp));
}
const std::string *String(const std::string &s)
{
return String(s.data(), s.size());
}
}

14
bin/intern.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef __intern_h__
#define __intern_h__
#include <string>
namespace Intern {
const std::string *String(const std::string &s);
const std::string *String(std::string &&s);
const std::string *String(const char *);
const std::string *String(const char *, size_t size);
const std::string *String(const char *, const char *);
};
#endif

View File

@ -6,40 +6,128 @@
namespace Debug {
enum {
// 0x8000 = pointer
// 0x1000 = unsigned
// 0x0f00 = size
// 0-255 - type
kSInt64 = 0x0800,
kUInt64 = 0x1800,
kSInt32 = 0x0400,
kUInt32 = 0x1400,
kSInt16 = 0x0200,
kUInt16 = 0x1200,
kSInt8 = 0x0100,
kUInt8 = 0x1100,
kStruct = 0x0000,
kStructPtr = 0x8000,
// ptrs are a special case where size = 0
//kVoid = 0x0001,
kVoidPtr = 0x8001,
// these exist for display purposes.
kCStringPtr = 0x8002,
kPStringPtr = 0x8003,
kOSType = 0x00404,
kBoolean = 0x0105,
kOSErr = 0x0206,
kHandle = 0x04007,
};
inline unsigned MakePtr(unsigned type) { return type | 0x8000; }
inline unsigned MakeType(unsigned size, bool sign, bool ptr) {
unsigned rv = size << 8;
if (!sign) rv |= 0x0100;
if (ptr) rv |= 0x8000;
return rv;
}
enum {
kUnknown = 0,
kStringPtr, // p-string
kCStringPtr, // c-string
kPtr,
kOSType, // four-cc
kBoolean, // unsigned char, display true/false
kDisplayNative = 0,
kDisplayStringPtr, // p-string
kDisplayCStringPtr, // c-string
kDisplayOSType, // four-cc
kDisplayBoolean, // unsigned char, display true/false
kDisplayOSErr,
};
struct Template;
#if 0
struct Type {
enum {
kSimpleType,
kStructType,
kPointerType,
};
uint16_t tag;
uint16_t size;
};
// handles [signed/unsigned] type, type[], *type, and *type[]
struct SimpleType : public Type {
unsigned rank:16; // int == int[1]
unsigned display:14; //
unsigned sign:1;
unsigned pointer:1;
SimpleType() {
tag = kSimpleType;
size = 0;
rank = 0;
display = 0;
sign = 0;
pointer = 0;
}
};
struct PointerType: public Type {
Type *type;
};
struct StructType : public Type {
unsigned total_size;
FieldEntry *firstField;
};
#endif
struct FieldEntry;
typedef FieldEntry *Template;
struct FieldEntry {
std::string *name;
unsigned type;
unsigned count;
Template *tmpl;
Template tmpl;
FieldEntry *next;
unsigned struct_size; // only populated for head entry.
};
struct Template {
unsigned type; // 0 for structs, < 256 for types.
FieldEntry *firstField;
unsigned size;
struct TemplateParseInfo {
std::unordered_map<std::string, Template> *templates;
std::unordered_map<std::string, unsigned> *types;
int LineNumber;
};
void CreateTypedef(const std::string *name, int type);
void CreateTemplate(const std::string *name, FieldEntry *firstField);
void CreateTypedef(const std::string *name, int type, TemplateParseInfo *);
void CreateTemplate(const std::string *name, FieldEntry *firstField, TemplateParseInfo *);
bool LoadTemplateFile(const std::string &filename, std::unordered_map<std::string, Template> &);
extern std::unordered_map<std::string, Template *> Templates;
extern int TemplateLine;
}
#endif

View File

@ -12,6 +12,7 @@
#include "template_parser.h"
#include "template.h"
#include "intern.h"
namespace {
@ -39,63 +40,26 @@ namespace {
}
unsigned int DJBHash(const char* begin, const char *end)
{
unsigned int hash = 5381;
unsigned int i = 0;
for(const char *iter = begin; iter != end; ++iter)
{
hash = ((hash << 5) + hash) + (*iter);
}
return hash;
}
std::unordered_multimap<unsigned, std::string *> InternTable;
const std::string *InternString(const char *begin, const char *end)
{
bool found = false;
unsigned hash = DJBHash(begin, end);
size_t length = end - begin;
auto range = InternTable.equal_range(hash);
auto iter = range.first;
auto endit = range.second;
for( ; iter != endit; ++iter)
{
// hash matches, make sure the string does.
const std::string *s = iter->second;
if (s->length() == length && std::memcmp(s->data(), begin, length) == 0)
return s;
}
// insert it.
std::string *s = new std::string(begin, end);
InternTable.emplace(std::make_pair(hash, s));
return s;
}
}
void TemplateParse(void *yyp, int yymajor, void *yyminor);
void *TemplateParseAlloc(void *(*mallocProc)(size_t));
void TemplateParseFree(void *p, void (*freeProc)(void*));
void TemplateParse(void *yyp, int yymajor, int yyminor)
void TemplateParse(void *yyp, int yymajor, void *yyminor, Debug::TemplateParseInfo *);
void TemplateParse(void *yyp, int yymajor, int yyminor, Debug::TemplateParseInfo *info)
{
TemplateParse(yyp, yymajor, &yyminor);
TemplateParse(yyp, yymajor, &yyminor, info);
}
void TemplateParse(void *yyp, int yymajor, const std::string *yyminor)
void TemplateParse(void *yyp, int yymajor, const std::string *yyminor, Debug::TemplateParseInfo *info)
{
TemplateParse(yyp, yymajor, (void *)yyminor);
TemplateParse(yyp, yymajor, (void *)yyminor, info);
}
#define TemplateParse(a,b,c) TemplateParse(a,b,c, &info)
%%{
machine lexer;
@ -103,14 +67,14 @@ void TemplateParse(void *yyp, int yymajor, const std::string *yyminor)
error := any* ${ fbreak; };
block_comment := |*
[\n\r] { TemplateLine++; };
[\n\r] { info.LineNumber++; };
'*/' { fgoto main; };
any ;
*|;
main := |*
[\n\r] { TemplateLine++; };
[\n\r] { info.LineNumber++; };
[ \t]+;
'//' [^\r\n]* ;
@ -139,24 +103,26 @@ void TemplateParse(void *yyp, int yymajor, const std::string *yyminor)
'signed' { TemplateParse(parser, tkSIGNED, 0); };
'unsigned' { TemplateParse(parser, tkUNSIGNED, 0); };
'int64_t' { TemplateParse(parser, tkTYPECODE, 'q'); };
'uint64_t' { TemplateParse(parser, tkTYPECODE, 'Q'); };
'int64_t' { TemplateParse(parser, tkTYPECODE, kSInt64); };
'uint64_t' { TemplateParse(parser, tkTYPECODE, kUInt64); };
'int32_t' { TemplateParse(parser, tkTYPECODE, 'l'); };
'uint32_t' { TemplateParse(parser, tkTYPECODE, 'L'); };
'int32_t' { TemplateParse(parser, tkTYPECODE, kSInt32); };
'uint32_t' { TemplateParse(parser, tkTYPECODE, kUInt32); };
'int16_t' { TemplateParse(parser, tkTYPECODE, 's'); };
'uint16_t' { TemplateParse(parser, tkTYPECODE, 'S'); };
'int16_t' { TemplateParse(parser, tkTYPECODE, kSInt16); };
'uint16_t' { TemplateParse(parser, tkTYPECODE, kUInt16); };
'int8_t' { TemplateParse(parser, tkTYPECODE, 'c'); };
'uint8_t' { TemplateParse(parser, tkTYPECODE, 'C'); };
'int8_t' { TemplateParse(parser, tkTYPECODE, kSInt8); };
'uint8_t' { TemplateParse(parser, tkTYPECODE, kUInt8); };
'StringPtr' { TemplateParse(parser, tkTYPECODE, kStringPtr); };
'StringPtr' { TemplateParse(parser, tkTYPECODE, kPStringPtr); };
'CStringPtr' { TemplateParse(parser, tkTYPECODE, kCStringPtr); };
'Ptr' { TemplateParse(parser, tkTYPECODE, kPtr); };
'Ptr' { TemplateParse(parser, tkTYPECODE, kVoidPtr); };
'OSType' { TemplateParse(parser, tkTYPECODE, kOSType); };
'OSErr' { TemplateParse(parser, tkTYPECODE, kOSErr); };
'Boolean' { TemplateParse(parser, tkTYPECODE, kBoolean); };
'Handle' { TemplateParse(parser, tkTYPECODE, kHandle); };
# numbers. negative numbers are not allowed.
@ -177,16 +143,26 @@ void TemplateParse(void *yyp, int yymajor, const std::string *yyminor)
// intern the string.
const std::string *name = InternString(ts, te);
const std::string *name = Intern::String(ts, te);
bool ok = false;
auto iter = Templates.find(*name);
if (iter != Templates.end())
{
unsigned type = iter->second->type;
if (type) TemplateParse(parser, tkTYPECODE, type);
else TemplateParse(parser, tkTEMPLATE, iter->second);
if (!ok) {
auto iter = Types.find(*name);
if (iter != Types.end())
{
TemplateParse(parser, tkTYPECODE, iter->second);
ok = true;
}
}
else
if (!ok) {
auto iter = Templates.find(*name);
if (iter != Templates.end())
{
TemplateParse(parser, tkTEMPLATE, iter->second);
ok = true;
}
}
if (!ok)
{
TemplateParse(parser, tkIDENTIFIER, name);
}
@ -198,18 +174,108 @@ void TemplateParse(void *yyp, int yymajor, const std::string *yyminor)
namespace Debug {
std::unordered_map<std::string, Template *> Templates;
void CreateTypedef(const std::string *name, int type)
{
}
void CreateTemplate(const std::string *name, FieldEntry *firstField)
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));
}
int TemplateLine;
unsigned CalcSize(FieldEntry *e)
{
unsigned size = 0;
bool ParseTemplates(const std::string &filename)
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)
{
%% write data;
@ -219,6 +285,17 @@ bool ParseTemplates(const std::string &filename)
struct stat st;
char *buffer;
std::unordered_map<std::string, unsigned> Types;
TemplateParseInfo info;
info.LineNumber = 1;
info.templates = &Templates;
info.types = &Types;
// simple types are handled via the lexer so no need to populate them here.
if (stat(filename.c_str(), &st) < 0) return false;
if (st.st_size == 0) return false;
@ -241,9 +318,6 @@ bool ParseTemplates(const std::string &filename)
parser = TemplateParseAlloc(malloc);
TemplateLine = 1;
const char *p = buffer;
const char *pe = buffer + st.st_size;
const char *eof = pe;
@ -272,7 +346,8 @@ bool ParseTemplates(const std::string &filename)
}
if (p == pe)
{
TemplateParse(parser, tkEOF, 0);
// ?
//TemplateParse(parser, tkEOF, 0);
break;
}
}

View File

@ -1,5 +1,7 @@
%token_prefix tk
%name TemplateParse
%extra_argument { Debug::TemplateParseInfo *info }
%include {
@ -13,24 +15,22 @@
%type struct_fields { FieldEntry * }
%type struct_field { FieldEntry * }
%type array_count { int }
%type opt_star { int }
%type typecode { int }
%type type { int }
start ::= templates EOF.
start ::= templates.
templates ::= templates struct.
templates ::= templates typedef.
templates ::= .
// typedeffing arrays or pointers is not allowed.
typedef ::= TYPEDEF type(a) IDENTIFIER(b). {
CreateTypedef((std::string *)b, a);
CreateTypedef((std::string *)b, a, info);
}
struct ::= STRUCT IDENTIFIER(a) LBRACE struct_fields(b) RBRACE SEMI.
{
CreateTemplate((std::string *)a, b);
CreateTemplate((std::string *)a, b, info);
}
struct_fields(rhs) ::= struct_fields(a) struct_field(b). {
@ -57,50 +57,63 @@ struct_field(rhs) ::= opt_volatile TEMPLATE(a) opt_star(star) IDENTIFIER(b) arra
FieldEntry *e = (FieldEntry *)calloc(sizeof(FieldEntry), 1);
e->name = (std::string *)b;
e->type = star ? kPtr : 0;
e->tmpl = (Template *)a;
e->type = star ? kStruct : kStructPtr;
e->tmpl = (Template)a;
e->count = c;
rhs = e;
}
array_count(rhs) ::= . { rhs = -1; }
array_count(rhs) ::= LBRACKET INTEGER(a) RBRACKET. { rhs = *(int *)a; }
%type array_count { int }
array_count(rhs) ::= . { rhs = 0; }
array_count(rhs) ::= LBRACKET INTEGER(a) RBRACKET. {
int i = *(int *)a;
if (i == 0) {
fprintf(stderr, "Template error: line %u: 0-sized arrays are not allowed.\n",
info->LineNumber);
i = 1;
}
rhs = i;
}
%type type { int }
type(rhs) ::= opt_volatile typecode(a). { rhs = a; }
// this is an expected error...
type(rhs) ::= opt_volatile IDENTIFIER(xxx). {
// ugh, Lemon will blindly replace text within a string.
fprintf(stderr, "Template error: line %u: %s is not a known type.\n",
TemplateLine, ((std::string *)xxx)->c_str());
info->LineNumber, ((std::string *)xxx)->c_str());
rhs = 'i';
}
type(rhs) ::= opt_volatile typecode(a). { rhs = a; }
opt_volatile ::= .
opt_volatile ::= VOLATILE.
typecode(rhs) ::= SIGNED. { rhs = 'i'; }
typecode(rhs) ::= UNSIGNED. {rhs = 'I'; }
typecode(rhs) ::= opt_signed CHAR. { rhs = 'c'; }
typecode(rhs) ::= UNSIGNED CHAR. { rhs = 'C'; }
%type typecode { int }
typecode(rhs) ::= SIGNED. { rhs = kSInt32; }
typecode(rhs) ::= UNSIGNED. {rhs = kUInt32; }
typecode(rhs) ::= opt_signed SHORT. { rhs = 's'; }
typecode(rhs) ::= UNSIGNED SHORT. { rhs = 'S'; }
typecode(rhs) ::= opt_signed CHAR. { rhs = kSInt8; }
typecode(rhs) ::= UNSIGNED CHAR. { rhs = kUInt8; }
typecode(rhs) ::= opt_signed LONG opt_int. { rhs = 'l'; }
typecode(rhs) ::= UNSIGNED LONG opt_int. { rhs = 'L'; }
typecode(rhs) ::= opt_signed SHORT. { rhs = kSInt16; }
typecode(rhs) ::= UNSIGNED SHORT. { rhs = kUInt16; }
typecode(rhs) ::= opt_signed LONG LONG. { rhs = 'q'; }
typecode(rhs) ::= UNSIGNED LONG LONG. { rhs = 'Q'; }
typecode(rhs) ::= opt_signed LONG opt_int. { rhs = kSInt32; }
typecode(rhs) ::= UNSIGNED LONG opt_int. { rhs = kUInt32; }
typecode(rhs) ::= opt_signed LONG LONG. { rhs = kSInt64; }
typecode(rhs) ::= UNSIGNED LONG LONG. { rhs = kUInt64; }
typecode(rhs) ::= TYPECODE(a). { rhs = *(int *)a; }
/* pointers are not fully supported yet */
typecode(rhs) ::= VOID STAR. { rhs = kPtr; }
typecode(rhs) ::= VOID STAR. { rhs = kVoidPtr; }
opt_signed ::= .
opt_signed ::= SIGNED.
@ -108,7 +121,7 @@ opt_signed ::= SIGNED.
opt_int ::= .
opt_int ::= INT.
%type opt_star { int }
opt_star(rhs) ::= . { rhs = 0; }
opt_star(rhs) ::= STAR. { rhs = 1; }