2006-08-26 11:35:28 +00:00
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: File stream wrapper that understands indentation
|
|
|
|
|
//
|
2008-04-25 12:14:27 +00:00
|
|
|
|
// Code available from: http://www.veripool.org/verilator
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//
|
|
|
|
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2009-01-02 16:47:39 +00:00
|
|
|
|
// Copyright 2003-2009 by Wilson Snyder. This program is free software; you can
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// redistribute it and/or modify it under the terms of either the GNU
|
2009-05-04 21:07:57 +00:00
|
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
// Version 2.0.
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//
|
|
|
|
|
// Verilator 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.
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
2006-12-18 19:20:45 +00:00
|
|
|
|
#include "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
2008-06-30 17:11:25 +00:00
|
|
|
|
#include <cstdarg>
|
2006-08-26 11:35:28 +00:00
|
|
|
|
#include <sys/stat.h>
|
2008-01-31 14:49:27 +00:00
|
|
|
|
#include <sys/types.h>
|
2006-08-26 11:35:28 +00:00
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <iomanip>
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
|
|
#include "V3Global.h"
|
|
|
|
|
#include "V3File.h"
|
|
|
|
|
#include "V3PreShell.h"
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// V3File Internal state
|
|
|
|
|
|
|
|
|
|
class V3FileDependImp {
|
|
|
|
|
// TYPES
|
|
|
|
|
class DependFile {
|
|
|
|
|
// A single file
|
|
|
|
|
bool m_target; // True if write, else read
|
|
|
|
|
string m_filename; // Filename
|
|
|
|
|
struct stat m_stat; // Stat information
|
|
|
|
|
public:
|
|
|
|
|
DependFile(const string& filename, bool target)
|
|
|
|
|
: m_target(target), m_filename(filename) {
|
|
|
|
|
m_stat.st_mtime = 0;
|
|
|
|
|
}
|
|
|
|
|
~DependFile() {}
|
|
|
|
|
const string& filename() const { return m_filename; }
|
|
|
|
|
bool target() const { return m_target; }
|
|
|
|
|
off_t size() const { return m_stat.st_size; }
|
|
|
|
|
time_t mtime() const { return m_stat.st_mtime; }
|
|
|
|
|
void loadStats() {
|
|
|
|
|
if (!m_stat.st_mtime) {
|
|
|
|
|
int err = stat(filename().c_str(), &m_stat);
|
|
|
|
|
if (err!=0) {
|
|
|
|
|
m_stat.st_mtime = 1;
|
|
|
|
|
// Not a error... This can occur due to `line directives in the .vpp files
|
|
|
|
|
UINFO(1,"-Info: File not statable: "<<filename()<<endl);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
bool operator<(const DependFile& rhs) const { return filename()<rhs.filename(); };
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// MEMBERS
|
|
|
|
|
set<string> m_filenameSet; // Files generated (elim duplicates)
|
|
|
|
|
set<DependFile> m_filenameList; // Files sourced/generated
|
|
|
|
|
|
|
|
|
|
static string stripQuotes(const string& in) {
|
|
|
|
|
string pretty = in;
|
|
|
|
|
string::size_type pos;
|
|
|
|
|
while ((pos=pretty.find("\"")) != string::npos) pretty.replace(pos, 1, "_");
|
|
|
|
|
while ((pos=pretty.find("\n")) != string::npos) pretty.replace(pos, 1, "_");
|
|
|
|
|
return pretty;
|
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
// ACCESSOR METHODS
|
|
|
|
|
void addSrcDepend(const string& filename) {
|
|
|
|
|
if (m_filenameSet.find(filename) == m_filenameSet.end()) {
|
|
|
|
|
m_filenameSet.insert(filename);
|
|
|
|
|
DependFile df (filename, false);
|
|
|
|
|
df.loadStats(); // Get size now, in case changes during the run
|
|
|
|
|
m_filenameList.insert(df);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void addTgtDepend(const string& filename) {
|
|
|
|
|
if (m_filenameSet.find(filename) == m_filenameSet.end()) {
|
|
|
|
|
m_filenameSet.insert(filename);
|
|
|
|
|
m_filenameList.insert(DependFile (filename, true));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void writeDepend(const string& filename);
|
|
|
|
|
void writeTimes(const string& filename, const string& cmdline);
|
|
|
|
|
bool checkTimes(const string& filename, const string& cmdline);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
V3FileDependImp dependImp; // Depend implementation class
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// V3FileDependImp
|
|
|
|
|
|
|
|
|
|
inline void V3FileDependImp::writeDepend(const string& filename) {
|
|
|
|
|
const auto_ptr<ofstream> ofp (V3File::new_ofstream(filename));
|
|
|
|
|
if (ofp->fail()) v3fatalSrc("Can't write "<<filename);
|
|
|
|
|
|
|
|
|
|
for (set<DependFile>::iterator iter=m_filenameList.begin();
|
|
|
|
|
iter!=m_filenameList.end(); ++iter) {
|
|
|
|
|
if (iter->target()) {
|
|
|
|
|
*ofp<<iter->filename()<<" ";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*ofp<<" : ";
|
|
|
|
|
*ofp<<v3Global.opt.bin();
|
|
|
|
|
*ofp<<" ";
|
|
|
|
|
*ofp<<V3PreShell::dependFiles();
|
|
|
|
|
*ofp<<" ";
|
|
|
|
|
|
|
|
|
|
for (set<DependFile>::iterator iter=m_filenameList.begin();
|
|
|
|
|
iter!=m_filenameList.end(); ++iter) {
|
|
|
|
|
if (!iter->target()) {
|
|
|
|
|
*ofp<<iter->filename()<<" ";
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-08-31 15:29:15 +00:00
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
*ofp<<endl;
|
2006-08-31 15:29:15 +00:00
|
|
|
|
|
|
|
|
|
if (v3Global.opt.makePhony()) {
|
|
|
|
|
*ofp<<endl;
|
|
|
|
|
for (set<DependFile>::iterator iter=m_filenameList.begin();
|
|
|
|
|
iter!=m_filenameList.end(); ++iter) {
|
|
|
|
|
if (!iter->target()) {
|
|
|
|
|
*ofp<<iter->filename()<<":"<<endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void V3FileDependImp::writeTimes(const string& filename, const string& cmdlineIn) {
|
|
|
|
|
const auto_ptr<ofstream> ofp (V3File::new_ofstream(filename));
|
|
|
|
|
if (ofp->fail()) v3fatalSrc("Can't write "<<filename);
|
|
|
|
|
|
|
|
|
|
string cmdline = stripQuotes(cmdlineIn);
|
|
|
|
|
*ofp<<"C \""<<cmdline<<"\""<<endl;
|
|
|
|
|
|
|
|
|
|
sync(); // Push files so sizes look correct
|
|
|
|
|
for (set<DependFile>::iterator iter=m_filenameList.begin();
|
|
|
|
|
iter!=m_filenameList.end(); ++iter) {
|
|
|
|
|
// Read stats of files we create after we're done making them (execpt for this file, of course)
|
|
|
|
|
DependFile* dfp = (DependFile*)&(*iter);
|
|
|
|
|
dfp->loadStats();
|
|
|
|
|
off_t showSize = iter->size();
|
|
|
|
|
if (dfp->filename() == filename) showSize=0; // We're writing it, so need to ignore it
|
|
|
|
|
|
|
|
|
|
*ofp<<(iter->target()?"T":"S")<<" ";
|
|
|
|
|
*ofp<<" "<<setw(8)<<showSize;
|
|
|
|
|
*ofp<<" "<<setw(11)<<iter->mtime();
|
|
|
|
|
*ofp<<" \""<<iter->filename()<<"\"";
|
|
|
|
|
*ofp<<endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline bool V3FileDependImp::checkTimes(const string& filename, const string& cmdlineIn) {
|
|
|
|
|
const auto_ptr<ifstream> ifp (V3File::new_ifstream_nodepend(filename));
|
|
|
|
|
if (ifp->fail()) {
|
|
|
|
|
UINFO(2," --check-times failed: no input "<<filename<<endl);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
char chkDir; *ifp>>chkDir;
|
|
|
|
|
char quote; *ifp>>quote;
|
|
|
|
|
string chkCmdline; getline(*ifp, chkCmdline, '"');
|
|
|
|
|
string cmdline = stripQuotes(cmdlineIn);
|
|
|
|
|
if (cmdline != chkCmdline) {
|
|
|
|
|
UINFO(2," --check-times failed: different command line\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (!ifp->eof()) {
|
|
|
|
|
char chkDir; *ifp>>chkDir;
|
|
|
|
|
off_t chkSize; *ifp>>chkSize;
|
|
|
|
|
if (ifp->eof()) break; // Needed to read final whitespace before found eof
|
|
|
|
|
time_t chkMtime; *ifp>>chkMtime;
|
|
|
|
|
char quote; *ifp>>quote;
|
|
|
|
|
string chkFilename; getline(*ifp, chkFilename, '"');
|
|
|
|
|
//UINFO(9," got d="<<chkDir<<" s="<<chkSize<<" mt="<<chkMtime<<" fn = "<<chkFilename<<endl);
|
|
|
|
|
|
|
|
|
|
struct stat chkStat;
|
|
|
|
|
int err = stat(chkFilename.c_str(), &chkStat);
|
|
|
|
|
if (err!=0) {
|
|
|
|
|
UINFO(2," --check-times failed: missing "<<chkFilename<<endl);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (filename != chkFilename) { // See above; we were writing it at the time...
|
|
|
|
|
// We'd like this rule:
|
|
|
|
|
//if (!(chkStat.st_size == chkSize
|
|
|
|
|
// && chkStat.st_mtime == chkMtime) {
|
|
|
|
|
// However NFS messes us up, as there might be some data outstanding when
|
|
|
|
|
// we determined the original size. For safety, we know the creation time
|
|
|
|
|
// must be within a few second window... call it 20 sec.
|
|
|
|
|
if (!(chkStat.st_size >= chkSize
|
|
|
|
|
&& chkStat.st_mtime >= chkMtime
|
|
|
|
|
&& chkStat.st_mtime <= (chkMtime + 20))) {
|
|
|
|
|
UINFO(2," --check-times failed: out-of-date "<<chkFilename
|
|
|
|
|
<<"; "<<chkStat.st_size<<"=?"<<chkSize
|
|
|
|
|
<<" "<<chkStat.st_mtime<<"=?"<<chkMtime<<endl);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// V3File
|
|
|
|
|
|
|
|
|
|
void V3File::addSrcDepend(const string& filename) {
|
|
|
|
|
dependImp.addSrcDepend(filename);
|
|
|
|
|
}
|
|
|
|
|
void V3File::addTgtDepend(const string& filename) {
|
|
|
|
|
dependImp.addTgtDepend(filename);
|
|
|
|
|
}
|
|
|
|
|
void V3File::writeDepend(const string& filename) {
|
|
|
|
|
dependImp.writeDepend(filename);
|
|
|
|
|
}
|
|
|
|
|
void V3File::writeTimes(const string& filename, const string& cmdline) {
|
|
|
|
|
dependImp.writeTimes(filename, cmdline);
|
|
|
|
|
}
|
|
|
|
|
bool V3File::checkTimes(const string& filename, const string& cmdline) {
|
|
|
|
|
return dependImp.checkTimes(filename, cmdline);
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-31 13:50:06 +00:00
|
|
|
|
void V3File::createMakeDir() {
|
|
|
|
|
static bool created = false;
|
|
|
|
|
if (!created) {
|
|
|
|
|
created = true;
|
|
|
|
|
mkdir(v3Global.opt.makeDir().c_str(), 0777);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//######################################################################
|
|
|
|
|
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
|
|
|
|
|
|
|
|
|
|
V3OutFile::V3OutFile(const string& filename)
|
2008-06-30 18:31:58 +00:00
|
|
|
|
: m_filename(filename), m_lineno(1), m_column(0)
|
|
|
|
|
, m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
|
|
|
|
|
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
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) {
|
|
|
|
|
// Indent the specified levelsber of spaces. Use tabs as possible.
|
|
|
|
|
static char str[MAXSPACE+20];
|
|
|
|
|
char* cp = str;
|
|
|
|
|
if (num>MAXSPACE) num=MAXSPACE;
|
|
|
|
|
while (num>=8) {
|
|
|
|
|
*cp++ = '\t';
|
|
|
|
|
num -= 8;
|
|
|
|
|
}
|
|
|
|
|
while (num>0) {
|
|
|
|
|
*cp++ = ' ';
|
|
|
|
|
num --;
|
|
|
|
|
}
|
|
|
|
|
*cp++ = '\0';
|
|
|
|
|
return (str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const string V3OutFile::indentSpaces(int num) {
|
|
|
|
|
// Indent the specified number of spaces. Use spaces.
|
|
|
|
|
static char str[MAXSPACE+20];
|
|
|
|
|
char* cp = str;
|
|
|
|
|
if (num>MAXSPACE) num=MAXSPACE;
|
|
|
|
|
while (num>0) {
|
|
|
|
|
*cp++ = ' ';
|
|
|
|
|
num --;
|
|
|
|
|
}
|
|
|
|
|
*cp++ = '\0';
|
|
|
|
|
string st (str);
|
|
|
|
|
return (st);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool V3OutFile::tokenStart(const char* cp, const char* cmp) {
|
|
|
|
|
while (*cmp == *cp) { cp++; cmp++; }
|
|
|
|
|
if (*cmp) return false;
|
|
|
|
|
if (*cp && !isspace(*cp)) return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define VERILOG_INDENTS 0 // No verilog output yet, speed things up
|
|
|
|
|
bool V3OutFile::tokenEnd(const char* cp) {
|
|
|
|
|
return (tokenStart(cp,"end")
|
|
|
|
|
|| tokenStart(cp,"endcase")
|
|
|
|
|
|| tokenStart(cp,"endmodule"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int V3OutFile::endLevels (const char *strg) {
|
|
|
|
|
int levels=m_indentLevel;
|
|
|
|
|
const char* cp=strg;
|
|
|
|
|
while (isspace(*cp)) cp++;
|
|
|
|
|
switch (*cp) {
|
|
|
|
|
case '\n': // Newlines.. No need for whitespace before it
|
|
|
|
|
return (0);
|
|
|
|
|
case '#': // Preproc directive
|
|
|
|
|
return (0);
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
// label/public/private: Deindent by 2 spaces
|
|
|
|
|
const char* mp=cp;
|
|
|
|
|
for (; isalnum(*mp); mp++) ;
|
|
|
|
|
if (mp[0]==':' && mp[1]!=':') return (levels-INDBLK/2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We want "} else {" to be one level to the left of normal
|
|
|
|
|
for (const char* cp=strg; *cp; cp++) {
|
|
|
|
|
switch (*cp) {
|
|
|
|
|
case '}':
|
|
|
|
|
case ')':
|
|
|
|
|
levels-=INDBLK;
|
|
|
|
|
break;
|
|
|
|
|
case 'e':
|
|
|
|
|
if (VERILOG_INDENTS && tokenEnd(cp)) {
|
|
|
|
|
levels-=INDBLK;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '\t':
|
|
|
|
|
case ' ':
|
|
|
|
|
break; // Continue
|
|
|
|
|
default:
|
|
|
|
|
return (levels); // Letter
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (levels);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void V3OutFile::puts (const char *strg) {
|
|
|
|
|
if (m_prependIndent) {
|
|
|
|
|
putsNoTracking(indentStr(endLevels(strg)));
|
|
|
|
|
m_prependIndent = false;
|
|
|
|
|
}
|
|
|
|
|
bool wordstart = true;
|
|
|
|
|
for (const char* cp=strg; *cp; cp++) {
|
|
|
|
|
putcNoTracking (*cp);
|
|
|
|
|
switch (*cp) {
|
|
|
|
|
case '\n':
|
|
|
|
|
m_lineno++;
|
|
|
|
|
wordstart = true;
|
|
|
|
|
if (cp[1]=='\0') {
|
|
|
|
|
m_prependIndent = true; // Add the indent later, may be a indentInc/indentDec called between now and then
|
|
|
|
|
} else {
|
|
|
|
|
m_prependIndent = false;
|
|
|
|
|
putsNoTracking(indentStr(endLevels(cp+1)));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
|
|
|
|
wordstart = true;
|
|
|
|
|
break;
|
|
|
|
|
case '\t':
|
|
|
|
|
wordstart = true;
|
|
|
|
|
break;
|
|
|
|
|
case '{':
|
|
|
|
|
indentInc();
|
|
|
|
|
break;
|
|
|
|
|
case '(':
|
|
|
|
|
indentInc();
|
|
|
|
|
m_parenVec.push(m_column);
|
|
|
|
|
break;
|
|
|
|
|
case '}':
|
|
|
|
|
indentDec();
|
|
|
|
|
break;
|
|
|
|
|
case ')':
|
|
|
|
|
if (!m_parenVec.empty()) m_parenVec.pop();
|
|
|
|
|
indentDec();
|
|
|
|
|
break;
|
|
|
|
|
case 'b':
|
|
|
|
|
if (wordstart && VERILOG_INDENTS && tokenStart(cp,"begin")) {
|
|
|
|
|
indentInc();
|
|
|
|
|
}
|
|
|
|
|
wordstart = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'c':
|
|
|
|
|
if (wordstart && VERILOG_INDENTS && (tokenStart(cp,"case")
|
|
|
|
|
|| tokenStart(cp,"casex")
|
|
|
|
|
|| tokenStart(cp,"casez"))) {
|
|
|
|
|
indentInc();
|
|
|
|
|
}
|
|
|
|
|
wordstart = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'e':
|
|
|
|
|
if (wordstart && VERILOG_INDENTS && tokenEnd(cp)) {
|
|
|
|
|
indentDec();
|
|
|
|
|
}
|
|
|
|
|
wordstart = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'm':
|
|
|
|
|
if (wordstart && VERILOG_INDENTS && tokenStart(cp,"module")) {
|
|
|
|
|
indentInc();
|
|
|
|
|
}
|
|
|
|
|
wordstart = false;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
wordstart = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void V3OutFile::putBreakExpr () {
|
|
|
|
|
if (!m_parenVec.empty()) putBreak();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add a line break if too wide
|
|
|
|
|
void V3OutFile::putBreak () {
|
|
|
|
|
if (!m_nobreak) {
|
|
|
|
|
//char s[1000]; sprintf(s,"{%d,%d}",m_column,m_parenVec.top()); putsNoTracking(s);
|
|
|
|
|
if (exceededWidth()) {
|
|
|
|
|
putcNoTracking('\n');
|
|
|
|
|
if (!m_parenVec.empty()) putsNoTracking(indentStr(m_parenVec.top()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void V3OutFile::putsNoTracking (const char *strg) {
|
|
|
|
|
// Don't track {}'s, probably because it's a $display format string
|
|
|
|
|
for (const char* cp=strg; *cp; cp++) {
|
|
|
|
|
putcNoTracking (*cp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void V3OutFile::putcNoTracking (char chr) {
|
|
|
|
|
switch (chr) {
|
|
|
|
|
case '\n':
|
|
|
|
|
m_lineno++;
|
|
|
|
|
m_column=0;
|
|
|
|
|
m_nobreak=true;
|
|
|
|
|
break;
|
|
|
|
|
case '\t':
|
|
|
|
|
m_column = ((m_column + 9)/8)*8;
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
|
|
|
|
case '(':
|
|
|
|
|
case '|':
|
|
|
|
|
case '&':
|
|
|
|
|
m_column++;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
m_column++;
|
|
|
|
|
m_nobreak=false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
fputc (chr, m_fp);
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-29 00:58:48 +00:00
|
|
|
|
void V3OutFile::putAlign (bool/*AlignClass*/ isStatic, int align, int size, const char* prefix) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
if (size==0) size=align;
|
|
|
|
|
int alignSize = size; if (alignSize>8) alignSize=8;
|
2006-08-29 00:58:48 +00:00
|
|
|
|
int& alignr = isStatic ? m_declSAlign : m_declNSAlign;
|
|
|
|
|
int padsize = alignSize - (alignr % alignSize);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
if (padsize && padsize!=alignSize) {
|
|
|
|
|
puts("char\t");
|
|
|
|
|
puts(prefix);
|
2006-08-29 00:58:48 +00:00
|
|
|
|
puts("__VpadToAlign"+cvtToStr(alignr)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
+"["+cvtToStr(padsize)+"];\n");
|
2006-08-29 00:58:48 +00:00
|
|
|
|
alignr += padsize;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
m_declPadNum++;
|
|
|
|
|
}
|
2006-08-29 00:58:48 +00:00
|
|
|
|
alignr += size;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
// Simple wrappers
|
|
|
|
|
|
|
|
|
|
void V3OutFile::printf (const char *fmt...) {
|
|
|
|
|
char sbuff[5000];
|
|
|
|
|
va_list ap;
|
|
|
|
|
va_start(ap,fmt);
|
|
|
|
|
vsprintf(sbuff,fmt,ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
this->puts(sbuff);
|
|
|
|
|
}
|
|
|
|
|
|