mirror of
https://github.com/ksherlock/mpw.git
synced 2025-01-03 04:30:32 +00:00
more template code
This commit is contained in:
parent
7691267dea
commit
1cd59d36f3
@ -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
101
bin/intern.cpp
Normal 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
14
bin/intern.h
Normal 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
|
122
bin/template.h
122
bin/template.h
@ -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
|
||||
|
@ -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;
|
||||
|
||||
if (!ok) {
|
||||
auto iter = Types.find(*name);
|
||||
if (iter != Types.end())
|
||||
{
|
||||
TemplateParse(parser, tkTYPECODE, iter->second);
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
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);
|
||||
TemplateParse(parser, tkTEMPLATE, iter->second);
|
||||
ok = true;
|
||||
}
|
||||
else
|
||||
}
|
||||
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 CreateTypedef(const std::string *name, int type, TemplateParseInfo *info)
|
||||
{
|
||||
}
|
||||
void CreateTemplate(const std::string *name, FieldEntry *firstField)
|
||||
// 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;
|
||||
}
|
||||
|
||||
int TemplateLine;
|
||||
if (Templates.find(*name) != Templates.end())
|
||||
{
|
||||
fprintf(stderr, "Template Error: line %d - redefining %s\n",
|
||||
info->LineNumber, name->c_str());
|
||||
|
||||
bool ParseTemplates(const std::string &filename)
|
||||
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)
|
||||
{
|
||||
%% 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;
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user