Add file/line information to entities and ports

Include the compiler infrastructure to vhdlpp for collecting the
file and line information and attaching it to entities and ports.
Make the parser store the file name during parse.

Create a libmisc library where I can put source files that are
used by multiple programs within the source tree.
This commit is contained in:
Stephen Williams
2011-01-18 17:03:51 -08:00
parent d72f7ea249
commit ab8f623cea
14 changed files with 42 additions and 338 deletions
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2000 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "LineInfo.h"
# include <sstream>
using namespace std;
LineInfo::LineInfo()
: lineno_(0)
{
}
LineInfo::~LineInfo()
{
}
string LineInfo::get_fileline() const
{
ostringstream buf;
buf << (file_.str()? file_.str() : "") << ":" << lineno_;
string res = buf.str();
return res;
}
void LineInfo::set_line(const LineInfo&that)
{
file_ = that.file_;
lineno_ = that.lineno_;
}
void LineInfo::set_file(perm_string f)
{
file_ = f;
}
void LineInfo::set_lineno(unsigned n)
{
lineno_ = n;
}
+57
View File
@@ -0,0 +1,57 @@
#ifndef __LineInfo_H
#define __LineInfo_H
/*
* Copyright (c) 1999-2009 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "StringHeap.h"
# include <string>
using namespace std;
/*
* This class holds line information for an internal object.
*
* Note that the file names are C-style strings that are allocated by
* the lexor (which parses the line directives) and are never
* deallocated. We can therefore safely store the pointer and never
* delete the string, even if LineInfo objects are destroyed.
*/
class LineInfo {
public:
LineInfo();
virtual ~LineInfo();
// Get a fully formatted file/lineno
string get_fileline() const;
// Set the file/line fro another LineInfo object.
void set_line(const LineInfo&that);
// Access parts of LineInfo data
void set_file(perm_string f);
void set_lineno(unsigned n);
perm_string get_file() const { return file_; }
unsigned get_lineno() const { return lineno_; }
private:
perm_string file_;
unsigned lineno_;
};
#endif
+201
View File
@@ -0,0 +1,201 @@
/*
* Copyright (c) 2002-2010 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "StringHeap.h"
# include <cstdlib>
# include <cstring>
# include <cassert>
#ifdef CHECK_WITH_VALGRIND
static char **string_pool = NULL;
static unsigned string_pool_count = 0;
#endif
StringHeap::StringHeap()
{
cell_base_ = 0;
cell_ptr_ = HEAPCELL;
cell_count_ = 0;
}
StringHeap::~StringHeap()
{
// This is a planned memory leak. The string heap is intended
// to hold permanently-allocated strings.
}
const char* StringHeap::add(const char*text)
{
unsigned len = strlen(text);
assert((len+1) <= HEAPCELL);
unsigned rem = HEAPCELL - cell_ptr_;
if (rem < (len+1)) {
cell_base_ = (char*)malloc(HEAPCELL);
#ifdef CHECK_WITH_VALGRIND
string_pool_count += 1;
string_pool = (char **) realloc(string_pool,
string_pool_count*sizeof(char **));
string_pool[string_pool_count-1] = cell_base_;
#endif
cell_ptr_ = 0;
cell_count_ += 1;
assert(cell_base_ != 0);
}
char*res = cell_base_ + cell_ptr_;
memcpy(res, text, len);
cell_ptr_ += len;
cell_base_[cell_ptr_++] = 0;
assert(cell_ptr_ <= HEAPCELL);
return res;
}
perm_string StringHeap::make(const char*text)
{
return perm_string(add(text));
}
StringHeapLex::StringHeapLex()
{
hit_count_ = 0;
add_count_ = 0;
for (unsigned idx = 0 ; idx < HASH_SIZE ; idx += 1)
hash_table_[idx] = 0;
}
StringHeapLex::~StringHeapLex()
{
}
void StringHeapLex::cleanup()
{
#ifdef CHECK_WITH_VALGRIND
for (unsigned idx = 0 ; idx < string_pool_count ; idx += 1) {
free(string_pool[idx]);
}
free(string_pool);
string_pool = NULL;
string_pool_count = 0;
for (unsigned idx = 0 ; idx < HASH_SIZE ; idx += 1) {
hash_table_[idx] = 0;
}
#endif
}
unsigned StringHeapLex::add_hit_count() const
{
return hit_count_;
}
unsigned StringHeapLex::add_count() const
{
return add_count_;
}
static unsigned hash_string(const char*text)
{
unsigned h = 0;
while (*text) {
h = (h << 4) ^ (h >> 28) ^ *text;
text += 1;
}
return h;
}
const char* StringHeapLex::add(const char*text)
{
unsigned hash_value = hash_string(text) % HASH_SIZE;
/* If we easily find the string in the hash table, then return
that and be done. */
if (hash_table_[hash_value]
&& (strcmp(hash_table_[hash_value], text) == 0)) {
hit_count_ += 1;
return hash_table_[hash_value];
}
/* The existing hash entry is not a match. Replace it with the
newly allocated value, and return the new pointer as the
result to the add. */
const char*res = StringHeap::add(text);
hash_table_[hash_value] = res;
add_count_ += 1;
return res;
}
perm_string StringHeapLex::make(const char*text)
{
return perm_string(add(text));
}
perm_string StringHeapLex::make(const string&text)
{
return perm_string(add(text.c_str()));
}
bool operator == (perm_string a, const char*b)
{
if (a.str() == b)
return true;
if (! (a.str() && b))
return false;
if (strcmp(a.str(), b) == 0)
return true;
return false;
}
bool operator == (perm_string a, perm_string b)
{
return a == b.str();
}
bool operator != (perm_string a, const char*b)
{
return ! (a == b);
}
bool operator != (perm_string a, perm_string b)
{
return ! (a == b);
}
bool operator < (perm_string a, perm_string b)
{
if (b.str() && !a.str())
return true;
if (b.str() == a.str())
return false;
if (strcmp(a.str(), b.str()) < 0)
return true;
return false;
}
+120
View File
@@ -0,0 +1,120 @@
#ifndef __StringHeap_H
#define __StringHeap_H
/*
* Copyright (c) 2002-2009 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include <string>
using namespace std;
class perm_string {
public:
perm_string() : text_(0) { }
perm_string(const perm_string&that) : text_(that.text_) { }
~perm_string() { }
perm_string& operator = (const perm_string&that)
{ text_ = that.text_; return *this; }
const char*str() const { return text_; }
operator const char* () const { return str(); }
// This is an escape for making perm_string objects out of
// literals. For example, perm_string::literal("Label"); Please
// do *not* cheat and pass arbitrary const char* items here.
static perm_string literal(const char*t) { return perm_string(t); }
private:
friend class StringHeap;
friend class StringHeapLex;
perm_string(const char*t) : text_(t) { };
private:
const char*text_;
};
extern bool operator == (perm_string a, perm_string b);
extern bool operator == (perm_string a, const char* b);
extern bool operator != (perm_string a, perm_string b);
extern bool operator != (perm_string a, const char* b);
extern bool operator > (perm_string a, perm_string b);
extern bool operator < (perm_string a, perm_string b);
extern bool operator >= (perm_string a, perm_string b);
extern bool operator <= (perm_string a, perm_string b);
/*
* The string heap is a way to permanently allocate strings
* efficiently. They only take up the space of the string characters
* and the terminating nul, there is no malloc overhead.
*/
class StringHeap {
public:
StringHeap();
~StringHeap();
const char*add(const char*);
perm_string make(const char*);
private:
enum { HEAPCELL = 0x10000 };
char*cell_base_;
unsigned cell_ptr_;
unsigned cell_count_;
private: // not implemented
StringHeap(const StringHeap&);
StringHeap& operator= (const StringHeap&);
};
/*
* A lexical string heap is a string heap that makes an effort to
* return the same pointer for identical strings. This saves further
* space by not allocating duplicate strings, so in a system with lots
* of identifiers, this can theoretically save more space.
*/
class StringHeapLex : private StringHeap {
public:
StringHeapLex();
~StringHeapLex();
const char*add(const char*);
perm_string make(const char*);
perm_string make(const string&);
unsigned add_count() const;
unsigned add_hit_count() const;
void cleanup();
private:
enum { HASH_SIZE = 4096 };
const char*hash_table_[HASH_SIZE];
unsigned add_count_;
unsigned hit_count_;
private: // not implemented
StringHeapLex(const StringHeapLex&);
StringHeapLex& operator= (const StringHeapLex&);
};
#endif