Internals: Split V3OutFile into separate formatter

This commit is contained in:
Wilson Snyder 2010-01-07 10:50:23 -05:00
parent eb63c8dcb8
commit a03a540156
2 changed files with 62 additions and 40 deletions

View File

@ -253,26 +253,19 @@ void V3File::createMakeDir() {
} }
//###################################################################### //######################################################################
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code. // V3OutFormatter: A class for printing to a file, with automatic indentation of C++ code.
V3OutFile::V3OutFile(const string& filename) V3OutFormatter::V3OutFormatter(const string& filename, bool verilog)
: m_filename(filename), m_lineno(1), m_column(0) : m_filename(filename), m_verilog(verilog)
, m_lineno(1), m_column(0)
, m_nobreak(false), m_prependIndent(true), m_indentLevel(0) , m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) { , m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
if ((m_fp = V3File::new_fopen_w(filename.c_str())) == NULL) {
v3fatal("Cannot write "<<filename);
}
}
V3OutFile::~V3OutFile() {
if (m_fp) fclose(m_fp);
m_fp = NULL;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
const char* V3OutFile::indentStr(int num) { const char* V3OutFormatter::indentStr(int num) {
// Indent the specified levelsber of spaces. Use tabs as possible. // Indent the specified number of spaces. Use tabs as possible.
static char str[MAXSPACE+20]; static char str[MAXSPACE+20];
char* cp = str; char* cp = str;
if (num>MAXSPACE) num=MAXSPACE; if (num>MAXSPACE) num=MAXSPACE;
@ -288,7 +281,7 @@ const char* V3OutFile::indentStr(int num) {
return (str); return (str);
} }
const string V3OutFile::indentSpaces(int num) { const string V3OutFormatter::indentSpaces(int num) {
// Indent the specified number of spaces. Use spaces. // Indent the specified number of spaces. Use spaces.
static char str[MAXSPACE+20]; static char str[MAXSPACE+20];
char* cp = str; char* cp = str;
@ -302,21 +295,20 @@ const string V3OutFile::indentSpaces(int num) {
return (st); return (st);
} }
bool V3OutFile::tokenStart(const char* cp, const char* cmp) { bool V3OutFormatter::tokenStart(const char* cp, const char* cmp) {
while (*cmp == *cp) { cp++; cmp++; } while (*cmp == *cp) { cp++; cmp++; }
if (*cmp) return false; if (*cmp) return false;
if (*cp && !isspace(*cp)) return false; if (*cp && !isspace(*cp)) return false;
return true; return true;
} }
#define VERILOG_INDENTS 0 // No verilog output yet, speed things up bool V3OutFormatter::tokenEnd(const char* cp) {
bool V3OutFile::tokenEnd(const char* cp) {
return (tokenStart(cp,"end") return (tokenStart(cp,"end")
|| tokenStart(cp,"endcase") || tokenStart(cp,"endcase")
|| tokenStart(cp,"endmodule")); || tokenStart(cp,"endmodule"));
} }
int V3OutFile::endLevels (const char *strg) { int V3OutFormatter::endLevels (const char *strg) {
int levels=m_indentLevel; int levels=m_indentLevel;
const char* cp=strg; const char* cp=strg;
while (isspace(*cp)) cp++; while (isspace(*cp)) cp++;
@ -341,7 +333,7 @@ int V3OutFile::endLevels (const char *strg) {
levels-=INDBLK; levels-=INDBLK;
break; break;
case 'e': case 'e':
if (VERILOG_INDENTS && tokenEnd(cp)) { if (m_verilog && tokenEnd(cp)) {
levels-=INDBLK; levels-=INDBLK;
} }
break; break;
@ -355,7 +347,7 @@ int V3OutFile::endLevels (const char *strg) {
return (levels); return (levels);
} }
void V3OutFile::puts (const char *strg) { void V3OutFormatter::puts (const char *strg) {
if (m_prependIndent) { if (m_prependIndent) {
putsNoTracking(indentStr(endLevels(strg))); putsNoTracking(indentStr(endLevels(strg)));
m_prependIndent = false; m_prependIndent = false;
@ -395,27 +387,27 @@ void V3OutFile::puts (const char *strg) {
indentDec(); indentDec();
break; break;
case 'b': case 'b':
if (wordstart && VERILOG_INDENTS && tokenStart(cp,"begin")) { if (wordstart && m_verilog && tokenStart(cp,"begin")) {
indentInc(); indentInc();
} }
wordstart = false; wordstart = false;
break; break;
case 'c': case 'c':
if (wordstart && VERILOG_INDENTS && (tokenStart(cp,"case") if (wordstart && m_verilog && (tokenStart(cp,"case")
|| tokenStart(cp,"casex") || tokenStart(cp,"casex")
|| tokenStart(cp,"casez"))) { || tokenStart(cp,"casez"))) {
indentInc(); indentInc();
} }
wordstart = false; wordstart = false;
break; break;
case 'e': case 'e':
if (wordstart && VERILOG_INDENTS && tokenEnd(cp)) { if (wordstart && m_verilog && tokenEnd(cp)) {
indentDec(); indentDec();
} }
wordstart = false; wordstart = false;
break; break;
case 'm': case 'm':
if (wordstart && VERILOG_INDENTS && tokenStart(cp,"module")) { if (wordstart && m_verilog && tokenStart(cp,"module")) {
indentInc(); indentInc();
} }
wordstart = false; wordstart = false;
@ -427,12 +419,12 @@ void V3OutFile::puts (const char *strg) {
} }
} }
void V3OutFile::putBreakExpr () { void V3OutFormatter::putBreakExpr () {
if (!m_parenVec.empty()) putBreak(); if (!m_parenVec.empty()) putBreak();
} }
// Add a line break if too wide // Add a line break if too wide
void V3OutFile::putBreak () { void V3OutFormatter::putBreak () {
if (!m_nobreak) { if (!m_nobreak) {
//char s[1000]; sprintf(s,"{%d,%d}",m_column,m_parenVec.top()); putsNoTracking(s); //char s[1000]; sprintf(s,"{%d,%d}",m_column,m_parenVec.top()); putsNoTracking(s);
if (exceededWidth()) { if (exceededWidth()) {
@ -442,7 +434,7 @@ void V3OutFile::putBreak () {
} }
} }
void V3OutFile::putsQuoted(const char* strg) { void V3OutFormatter::putsQuoted(const char* strg) {
// Quote \ and " for use inside C programs // Quote \ and " for use inside C programs
// Don't use to quote a filename for #include - #include doesn't \ escape. // Don't use to quote a filename for #include - #include doesn't \ escape.
putcNoTracking('"'); putcNoTracking('"');
@ -452,14 +444,14 @@ void V3OutFile::putsQuoted(const char* strg) {
} }
putcNoTracking('"'); putcNoTracking('"');
} }
void V3OutFile::putsNoTracking (const char *strg) { void V3OutFormatter::putsNoTracking (const char *strg) {
// Don't track {}'s, probably because it's a $display format string // Don't track {}'s, probably because it's a $display format string
for (const char* cp=strg; *cp; cp++) { for (const char* cp=strg; *cp; cp++) {
putcNoTracking (*cp); putcNoTracking (*cp);
} }
} }
void V3OutFile::putcNoTracking (char chr) { void V3OutFormatter::putcNoTracking (char chr) {
switch (chr) { switch (chr) {
case '\n': case '\n':
m_lineno++; m_lineno++;
@ -480,10 +472,10 @@ void V3OutFile::putcNoTracking (char chr) {
m_nobreak=false; m_nobreak=false;
break; break;
} }
fputc (chr, m_fp); putcOutput (chr);
} }
void V3OutFile::putAlign (bool/*AlignClass*/ isStatic, int align, int size, const char* prefix) { void V3OutFormatter::putAlign (bool/*AlignClass*/ isStatic, int align, int size, const char* prefix) {
if (size==0) size=align; if (size==0) size=align;
int alignSize = size; if (alignSize>8) alignSize=8; int alignSize = size; if (alignSize>8) alignSize=8;
int& alignr = isStatic ? m_declSAlign : m_declNSAlign; int& alignr = isStatic ? m_declSAlign : m_declNSAlign;
@ -504,7 +496,7 @@ void V3OutFile::putAlign (bool/*AlignClass*/ isStatic, int align, int size, cons
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Simple wrappers // Simple wrappers
void V3OutFile::printf (const char *fmt...) { void V3OutFormatter::printf (const char *fmt...) {
char sbuff[5000]; char sbuff[5000];
va_list ap; va_list ap;
va_start(ap,fmt); va_start(ap,fmt);
@ -513,3 +505,17 @@ void V3OutFile::printf (const char *fmt...) {
this->puts(sbuff); this->puts(sbuff);
} }
//######################################################################
// V3OutFormatter: A class for printing to a file, with automatic indentation of C++ code.
V3OutFile::V3OutFile(const string& filename)
: V3OutFormatter(filename, false) {
if ((m_fp = V3File::new_fopen_w(filename.c_str())) == NULL) {
v3fatal("Cannot write "<<filename);
}
}
V3OutFile::~V3OutFile() {
if (m_fp) fclose(m_fp);
m_fp = NULL;
}

View File

@ -72,9 +72,9 @@ public:
}; };
//============================================================================ //============================================================================
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code. // V3OutFormatter: A class for automatic indentation of C++ or Verilog code.
class V3OutFile { class V3OutFormatter {
// TYPES // TYPES
enum MiscConsts { enum MiscConsts {
INDBLK = 4, // Indentation per block level INDBLK = 4, // Indentation per block level
@ -87,8 +87,8 @@ public:
private: private:
// MEMBERS // MEMBERS
FILE* m_fp;
string m_filename; string m_filename;
bool m_verilog; // Indenting Verilog code
int m_lineno; int m_lineno;
int m_column; int m_column;
int m_nobreak; // Basic operator or begin paren, don't break next int m_nobreak; // Basic operator or begin paren, don't break next
@ -101,10 +101,11 @@ private:
int endLevels(const char* strg); int endLevels(const char* strg);
static const char* indentStr(int levels); static const char* indentStr(int levels);
void putcNoTracking(char chr);
public: public:
V3OutFile(const string& filename); V3OutFormatter(const string& filename, bool verilog);
~V3OutFile(); virtual ~V3OutFormatter() {}
// ACCESSORS // ACCESSORS
int column() const { return m_column; } int column() const { return m_column; }
// METHODS // METHODS
@ -132,8 +133,23 @@ public:
void blockDec() { if (!m_parenVec.empty()) m_parenVec.pop(); } void blockDec() { if (!m_parenVec.empty()) m_parenVec.pop(); }
// STATIC METHODS // STATIC METHODS
static const string indentSpaces(int levels); static const string indentSpaces(int levels);
// CALLBACKS - MUST OVERRIDE
virtual void putcOutput(char chr) = 0;
};
//============================================================================
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
class V3OutFile : public V3OutFormatter {
// MEMBERS
FILE* m_fp;
public:
V3OutFile(const string& filename);
virtual ~V3OutFile();
private: private:
void putcNoTracking(char chr); // CALLBACKS
virtual void putcOutput(char chr) { fputc(chr, m_fp); }
}; };
#endif // Guard #endif // Guard