Fix string corruption, bug780.

This commit is contained in:
Wilson Snyder 2014-06-08 21:36:18 -04:00
parent 69468708e2
commit 6cf50e6579
23 changed files with 126 additions and 88 deletions

View File

@ -29,6 +29,8 @@ indicates the contributor was also the author of the fix; Thanks!
**** Fix ENDLABEL warnings on escaped identifiers.
**** Fix string corruption, bug780. [Derek Lockhart]
* Verilator 3.860 2014-05-11

View File

@ -1250,9 +1250,9 @@ void VerilatedScope::scopeDump() const {
m_callbacksp[i], VerilatedImp::exportName(i));
}
}
if (varsp()) {
for (VerilatedVarNameMap::const_iterator it = varsp()->begin();
it != varsp()->end(); ++it) {
if (VerilatedVarNameMap* varsp = this->varsp()) {
for (VerilatedVarNameMap::const_iterator it = varsp->begin();
it != varsp->end(); ++it) {
VL_PRINTF(" VAR %p: %s\n", &(it->second), it->first);
}
}

View File

@ -62,8 +62,9 @@ bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t siz
VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) {
if (VL_UNLIKELY(readDiffers(datap,size))) {
string fn = filename();
string msg = (string)"Can't deserialize save-restore file as was made from different model";
vl_fatal(filename().c_str(), 0, "", msg.c_str());
vl_fatal(fn.c_str(), 0, "", msg.c_str());
close();
}
return *this; // For function chaining
@ -82,8 +83,9 @@ void VerilatedSerialize::header() {
void VerilatedDeserialize::header() {
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
string fn = filename();
string msg = (string)"Can't deserialize; file has wrong header signature";
vl_fatal(filename().c_str(), 0, "", msg.c_str());
vl_fatal(fn.c_str(), 0, "", msg.c_str());
close();
}
os.read(Verilated::serializedPtr(), Verilated::serializedSize());
@ -98,8 +100,9 @@ void VerilatedSerialize::trailer() {
void VerilatedDeserialize::trailer() {
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
string fn = filename();
string msg = (string)"Can't deserialize; file has wrong end-of-file signature";
vl_fatal(filename().c_str(), 0, "", msg.c_str());
vl_fatal(fn.c_str(), 0, "", msg.c_str());
close();
}
}

View File

@ -172,8 +172,8 @@ void VerilatedVcd::makeNameMap() {
// This comes from user instantiations with no name - IE Vtop("").
bool nullScope = false;
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const char* hiername = (*it).first.c_str();
if (hiername[0] == '\t') nullScope=true;
const string& hiername = it->first;
if (hiername.size() >= 1 && hiername[0] == '\t') nullScope=true;
}
if (nullScope) {
NameMap* newmapp = new NameMap;
@ -352,7 +352,8 @@ void VerilatedVcd::dumpHeader () {
printStr("$date "); printStr(ctime(&time_str)); printStr(" $end\n");
printStr("$timescale ");
printStr(doubleToTimescale(m_timeRes).c_str());
const string& timeResStr = doubleToTimescale(m_timeRes);
printStr(timeResStr.c_str());
printStr(" $end\n");
makeNameMap();
@ -370,10 +371,11 @@ void VerilatedVcd::dumpHeader () {
// Print the signal names
const char* lastName = "";
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
const char* hiername = (*it).first.c_str();
const char* decl = (*it).second.c_str();
const string& hiernamestr = it->first;
const string& decl = it->second;
// Determine difference between the old and new names
const char* hiername = hiernamestr.c_str();
const char* lp = lastName;
const char* np = hiername;
lastName = hiername;
@ -408,7 +410,7 @@ void VerilatedVcd::dumpHeader () {
}
printIndent(0);
printStr(decl);
printStr(decl.c_str());
}
while (m_modDepth>1) {

View File

@ -259,10 +259,11 @@ public:
virtual const vluint32_t type() { return vpiIterator; }
virtual vpiHandle dovpi_scan() {
if (VL_LIKELY(m_scopep->varsp())) {
if (VL_UNLIKELY(!m_started)) { m_it = m_scopep->varsp()->begin(); m_started=true; }
else if (VL_UNLIKELY(m_it == m_scopep->varsp()->end())) return 0;
VerilatedVarNameMap* varsp = m_scopep->varsp();
if (VL_UNLIKELY(!m_started)) { m_it = varsp->begin(); m_started=true; }
else if (VL_UNLIKELY(m_it == varsp->end())) return 0;
else ++m_it;
if (m_it == m_scopep->varsp()->end()) return 0;
if (m_it == varsp->end()) return 0;
return ((new VerilatedVpioVar(&(m_it->second), m_scopep))
->castVpiHandle());
} else {
@ -430,15 +431,10 @@ class VerilatedVpiError {
t_vpi_error_info m_errorInfo;
bool m_flag;
char m_buff[VL_VPI_LINE_SIZE];
void setError(PLI_BYTE8 *message, PLI_BYTE8 *file, PLI_INT32 line) {
void setError(PLI_BYTE8 *message, PLI_BYTE8 *code, PLI_BYTE8 *file, PLI_INT32 line) {
m_errorInfo.message = message;
m_errorInfo.file = file;
m_errorInfo.line = line;
m_errorInfo.code = NULL;
do_callbacks();
}
void setError(PLI_BYTE8 *message, PLI_BYTE8 *code, PLI_BYTE8 *file, PLI_INT32 line) {
setError( message, file, line);
m_errorInfo.code = code;
do_callbacks();
}
@ -464,14 +460,11 @@ public:
return this;
}
void setMessage(string file, PLI_INT32 line, string message, ...) {
static VL_THREAD string filehold;
_VL_VPI_ERROR_SET;
m_errorInfo.state = vpiPLI;
setError((PLI_BYTE8*)m_buff, (PLI_BYTE8*)file.c_str(), line);
}
void setMessage(PLI_BYTE8 *code, PLI_BYTE8 *file, PLI_INT32 line, string message, ...) {
_VL_VPI_ERROR_SET;
m_errorInfo.state = vpiPLI;
setError((PLI_BYTE8*)message.c_str(), code, file, line);
filehold = file;
setError((PLI_BYTE8*)m_buff, NULL, (PLI_BYTE8*)filehold.c_str(), line);
}
p_vpi_error_info getError() {
if (m_flag) return &m_errorInfo;

View File

@ -915,8 +915,8 @@ ostream& operator<<(ostream& os, V3Hash rhs) {
V3Hash::V3Hash(const string& name) {
uint32_t val = 0;
for (const char* c=name.c_str(); *c; c++) {
val = val*31 + *c;
for (string::const_iterator it = name.begin(); it!=name.end(); ++it) {
val = val*31 + *it;
}
setBoth(1,val);
}

View File

@ -1696,8 +1696,9 @@ private:
string fmt = "";
bool inPct = false;
AstNode* argp = nodep->exprsp();
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
char ch = *inp; // Breaks with iterators...
string text = nodep->text();
for (string::const_iterator it = text.begin(); it!=text.end(); ++it) {
char ch = *it;
if (!inPct && ch=='%') {
inPct = true;
fmt = ch;

View File

@ -246,12 +246,14 @@ public:
char format = '?';
bool pct=false;
int got=0;
for (const char* cp = nodep->text().c_str(); *cp; cp++) {
string txt = nodep->text();
for (string::const_iterator it=txt.begin(); it!=txt.end(); ++it) {
char ch = *it;
if (pct) {
pct = false;
switch (tolower(*cp)) {
switch (tolower(ch)) {
case '%':
prefix += *cp;
prefix += ch;
break;
case 'd': // FALLTHRU
case 'o': // FALLTHRU
@ -259,22 +261,22 @@ public:
case 'x': // FALLTHRU
case 'b': // FALLTHRU
case 's':
got++; format = tolower(*cp);
got++; format = tolower(ch);
break;
case 'e': // FALLTHRU
case 'f': // FALLTHRU
case 'g':
got++; format = tolower(*cp);
nodep->v3error("Unsupported $value$plusargs format qualifier: '"<<*cp<<"'"<<endl);
got++; format = tolower(ch);
nodep->v3error("Unsupported $value$plusargs format qualifier: '"<<ch<<"'"<<endl);
break;
default:
got++;
nodep->v3error("Illegal $value$plusargs format qualifier: '"<<*cp<<"'"<<endl);
nodep->v3error("Illegal $value$plusargs format qualifier: '"<<ch<<"'"<<endl);
break;
}
}
else if (*cp == '%') pct = true;
else prefix += *cp;
else if (ch == '%') pct = true;
else prefix += ch;
}
if (got!=1) nodep->v3error("Missing or extra $value$plusargs format qualifier: '"<<nodep->text()<<"'"<<endl);
puts("VL_VALUEPLUSARGS_I");
@ -1382,7 +1384,7 @@ void EmitCImp::emitVarResets(AstNodeModule* modp) {
}
bool zeroit = (varp->attrFileDescr() // Zero it out, so we don't core dump if never call $fopen
|| (varp->basicp() && varp->basicp()->isZeroInit())
|| (varp->name().c_str()[0]=='_' && v3Global.opt.underlineZero()));
|| (varp->name().size()>=1 && varp->name()[0]=='_' && v3Global.opt.underlineZero()));
if (varp->isWide()) {
// DOCUMENT: We randomize everything. If the user wants a _var to be zero,
// there should be a initial statement. (Different from verilator2.)

View File

@ -383,7 +383,8 @@ void EmitCSyms::emitSymImp() {
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
if (modp->isTop()) {
} else {
ofp()->printf("\t%c %-30s ", comma, scopep->nameDotless().c_str());
string nameDl = scopep->nameDotless();
ofp()->printf("\t%c %-30s ", comma, nameDl.c_str());
puts("(Verilated::catName(topp->name(),");
// The "." is added by catName
putsQuoted(scopep->prettyName());

View File

@ -164,16 +164,16 @@ public:
of.puts("# User CFLAGS (from -CFLAGS on Verilator command line)\n");
of.puts("VM_USER_CFLAGS = \\\n");
for (V3StringSet::const_iterator it = v3Global.opt.cFlags().begin();
it != v3Global.opt.cFlags().end(); ++it) {
const V3StringSet& cFlags = v3Global.opt.cFlags();
for (V3StringSet::const_iterator it = cFlags.begin(); it != cFlags.end(); ++it) {
of.puts("\t"+*it+" \\\n");
}
of.puts("\n");
of.puts("# User LDLIBS (from -LDFLAGS on Verilator command line)\n");
of.puts("VM_USER_LDLIBS = \\\n");
for (V3StringSet::const_iterator it = v3Global.opt.ldLibs().begin();
it != v3Global.opt.ldLibs().end(); ++it) {
const V3StringSet& ldLibs = v3Global.opt.ldLibs();
for (V3StringSet::const_iterator it = ldLibs.begin(); it != ldLibs.end(); ++it) {
of.puts("\t"+*it+" \\\n");
}
of.puts("\n");
@ -181,8 +181,8 @@ public:
V3StringSet dirs;
of.puts("# User .cpp files (from .cpp's on Verilator command line)\n");
of.puts("VM_USER_CLASSES = \\\n");
for (V3StringSet::const_iterator it = v3Global.opt.cppFiles().begin();
it != v3Global.opt.cppFiles().end(); ++it) {
const V3StringSet& cppFiles = v3Global.opt.cppFiles();
for (V3StringSet::const_iterator it = cppFiles.begin(); it != cppFiles.end(); ++it) {
string cppfile = *it;
of.puts("\t"+V3Options::filenameNonExt(cppfile)+" \\\n");
string dir = V3Options::filenameDir(cppfile);
@ -207,8 +207,7 @@ public:
of.puts("\n### Executable rules... (from --exe)\n");
of.puts("VPATH += $(VM_USER_DIR)\n");
of.puts("\n");
for (V3StringSet::const_iterator it = v3Global.opt.cppFiles().begin();
it != v3Global.opt.cppFiles().end(); ++it) {
for (V3StringSet::const_iterator it = cppFiles.begin(); it != cppFiles.end(); ++it) {
string cppfile = *it;
string basename = V3Options::filenameNonExt(cppfile);
of.puts(basename+".o: "+cppfile+"\n");

View File

@ -71,7 +71,8 @@ class V3FileDependImp {
time_t mtime() const { return m_stat.st_mtime; }
void loadStats() {
if (!m_stat.st_mtime) {
int err = stat(filename().c_str(), &m_stat);
string fn = filename();
int err = stat(fn.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
@ -258,15 +259,19 @@ bool V3File::checkTimes(const string& filename, const string& cmdline) {
return dependImp.checkTimes(filename, cmdline);
}
void V3File::createDir(const string& dirname) {
#ifndef _WIN32
mkdir(dirname.c_str(), 0777);
#else
mkdir(dirname.c_str());
#endif
}
void V3File::createMakeDir() {
static bool created = false;
if (!created) {
created = true;
#ifndef _WIN32
mkdir(v3Global.opt.makeDir().c_str(), 0777);
#else
mkdir(v3Global.opt.makeDir().c_str());
#endif
createDir(v3Global.opt.makeDir());
}
}

View File

@ -67,6 +67,7 @@ public:
static bool checkTimes(const string& filename, const string& cmdline);
// Directory utilities
static void createDir(const string& dirname);
static void createMakeDir();
};
@ -188,8 +189,8 @@ public:
}
virtual ~V3OutCFile() {}
virtual void putsCellDecl(const string& classname, const string& cellname) {
this->printf("%-19s\t%s;\n",
(classname + "*").c_str(),cellname.c_str());
string classStar = classname + "*";
this->printf("%-19s\t%s;\n", classStar.c_str(), cellname.c_str());
}
virtual void putsHeader() { puts("// Verilated -*- C++ -*-\n"); }
virtual void putsIntTopInclude() { }

View File

@ -258,8 +258,8 @@ public:
if (!m_substTreep) {
clearSimple("No assignment found\n");
}
for (GateVarRefList::const_iterator it = rhsVarRefs().begin();
it != rhsVarRefs().end(); ++it) {
for (GateVarRefList::const_iterator it = m_rhsVarRefs.begin();
it != m_rhsVarRefs.end(); ++it) {
if (m_lhsVarRef && m_lhsVarRef->varScopep() == (*it)->varScopep()) {
clearSimple("Circular logic\n"); // Oh my, we'll get a UNOPTFLAT much later.
}
@ -593,8 +593,9 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
optimizeElimVar(vvertexp->varScp(), substp, consumerp);
// If the new replacement referred to a signal,
// Correct the graph to point to this new generating variable
for (GateVarRefList::const_iterator it = okVisitor.rhsVarRefs().begin();
it != okVisitor.rhsVarRefs().end(); ++it) {
const GateVarRefList& rhsVarRefs = okVisitor.rhsVarRefs();
for (GateVarRefList::const_iterator it = rhsVarRefs.begin();
it != rhsVarRefs.end(); ++it) {
AstVarScope* newvarscp = (*it)->varScopep();
UINFO(9," Point-to-new vertex "<<newvarscp<<endl);
GateVarVertex* varvertexp = makeVarVertex(newvarscp);

View File

@ -250,8 +250,8 @@ private:
void expectFormat(AstNode* nodep, const string& format, AstNode* argp, bool isScan) {
// Check display arguments
bool inPct = false;
for (const char* inp = format.c_str(); *inp; inp++) {
char ch = tolower(*inp); // Breaks with iterators...
for (string::const_iterator it = format.begin(); it != format.end(); ++it) {
char ch = tolower(*it);
if (!inPct && ch=='%') {
inPct = true;
} else if (inPct) {

View File

@ -622,13 +622,14 @@ void V3Options::parseOpts (FileLine* fl, int argc, char** argv) {
// Default certain options and error check
// Detailed error, since this is what we often get when run with minimal arguments
if (vFiles().empty()) {
const V3StringList& vFilesList = vFiles();
if (vFilesList.empty()) {
v3fatal("verilator: No Input Verilog file specified on command line, see verilator --help for more information\n");
}
// Default prefix to the filename
if (prefix()=="" && topModule()!="") m_prefix = string("V")+topModule();
if (prefix()=="") m_prefix = string("V")+filenameNonExt(*(vFiles().begin()));
if (prefix()=="" && vFilesList.size()>=1) m_prefix = string("V")+filenameNonExt(*(vFilesList.begin()));
if (modPrefix()=="") m_modPrefix = prefix();
// Find files in makedir

View File

@ -1191,14 +1191,14 @@ void OrderVisitor::processMove() {
while (!m_pomReadyDomScope.empty()) {
// Start with top node on ready list's domain & scope
OrderMoveDomScope* domScopep = m_pomReadyDomScope.begin();
OrderMoveVertex* topVertexp = domScopep->readyVertices().begin();
OrderMoveVertex* topVertexp = domScopep->readyVertices().begin(); // lintok-begin-on-ref
UASSERT(topVertexp, "domScope on ready list without any nodes ready under it");
// Work on all scopes ready inside this domain
while (domScopep) {
UINFO(6," MoveDomain l="<<domScopep->domainp()<<endl);
// Process all nodes ready under same domain & scope
m_pomNewFuncp = NULL;
while (OrderMoveVertex* vertexp = domScopep->readyVertices().begin()) {
while (OrderMoveVertex* vertexp = domScopep->readyVertices().begin()) { // lintok-begin-on-ref
processMoveOne(vertexp, domScopep, 1);
}
// Done with scope/domain pair, pick new scope under same domain, or NULL if none left

View File

@ -107,7 +107,7 @@ psl [p]sl
/* Optional directives we recognize */
<INITIAL>"`__FILE__" { static string rtnfile;
rtnfile = '"'; rtnfile += LEXP->curFilelinep()->filename().c_str();
rtnfile = '"'; rtnfile += LEXP->curFilelinep()->filename();
rtnfile += '"'; yytext=(char*)rtnfile.c_str(); yyleng = rtnfile.length();
return (VP_STRING); }
<INITIAL>"`__LINE__" { static char buf[10];

View File

@ -566,7 +566,8 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) {
bool quote = false;
bool haveDefault = false;
// Note there's a leading ( and trailing ), so parens==1 is the base parsing level
const char* cp=refp->params().c_str();
string params = refp->params(); // Must keep in scope
const char* cp=params.c_str();
if (*cp == '(') cp++;
for (; *cp; cp++) {
//UINFO(4," Parse Paren="<<paren<<" Arg="<<numArgs<<" token='"<<token<<"' Parse="<<cp<<endl);
@ -1367,9 +1368,11 @@ int V3PreProcImp::getFinalToken(string& buf) {
}
int tok = m_finToken;
buf = m_finBuf;
if (0 && debug()>=5) fprintf (stderr,"%d: FIN: %-10s: %s\n",
m_lexp->m_tokFilelinep->lineno(),
tokenName(tok), V3PreLex::cleanDbgStrg(buf).c_str());
if (0 && debug()>=5) {
string bufcln = V3PreLex::cleanDbgStrg(buf);
fprintf (stderr,"%d: FIN: %-10s: %s\n",
m_lexp->m_tokFilelinep->lineno(), tokenName(tok), bufcln.c_str());
}
// Track `line
const char* bufp = buf.c_str();
while (*bufp == '\n') bufp++;
@ -1400,7 +1403,7 @@ int V3PreProcImp::getFinalToken(string& buf) {
}
}
// Track newlines in prep for next token
for (const char* cp = buf.c_str(); *cp; cp++) {
for (string::iterator cp=buf.begin(); cp!=buf.end(); ++cp) {
if (*cp == '\n') {
m_finAtBol = true;
m_finFilelinep->linenoIncInPlace(); // Increment in place to avoid new/delete calls. It's private data.
@ -1422,8 +1425,9 @@ string V3PreProcImp::getline() {
string buf;
int tok = getFinalToken(buf/*ref*/);
if (debug()>=5) {
string bufcln = V3PreLex::cleanDbgStrg(buf);
fprintf (stderr,"%d: GETFETC: %-10s: %s\n",
m_lexp->m_tokFilelinep->lineno(), tokenName(tok), V3PreLex::cleanDbgStrg(buf).c_str());
m_lexp->m_tokFilelinep->lineno(), tokenName(tok), bufcln.c_str());
}
if (tok==VP_EOF) {
// Add a final newline, if the user forgot the final \n.
@ -1444,8 +1448,10 @@ string V3PreProcImp::getline() {
int len = rtnp-m_lineChars.c_str()+1;
string theLine(m_lineChars, 0, len);
m_lineChars = m_lineChars.erase(0,len); // Remove returned characters
if (debug()>=4) fprintf (stderr,"%d: GETLINE: %s\n",
m_lexp->m_tokFilelinep->lineno(),
V3PreLex::cleanDbgStrg(theLine).c_str());
if (debug()>=4) {
string lncln = V3PreLex::cleanDbgStrg(theLine);
fprintf (stderr,"%d: GETLINE: %s\n",
m_lexp->m_tokFilelinep->lineno(), lncln.c_str());
}
return theLine;
}

View File

@ -73,7 +73,7 @@ private:
return "Verilator trace_off";
}
else if (!v3Global.opt.traceUnderscore()) {
if (prettyName.c_str()[0] == '_')
if (prettyName.size()>=1 && prettyName[0] == '_')
return "Leading underscore";
if (prettyName.find("._") != string::npos)
return "Inlined leading underscore";

View File

@ -145,9 +145,10 @@ public:
return isUsedNotDrivenBit(0, m_flags.size()/FLAGS_PER_BIT);
}
bool unusedMatch(AstVar* nodep) {
const char* regexpp = v3Global.opt.unusedRegexp().c_str();
if (!regexpp || !*regexpp) return false;
return VString::wildmatch(nodep->prettyName().c_str(), regexpp);
string regexp = v3Global.opt.unusedRegexp();
if (regexp == "") return false;
string prettyName = nodep->prettyName();
return VString::wildmatch(prettyName.c_str(), regexp.c_str());
}
void reportViolations() {
// Combine bits into overall state

View File

@ -1678,8 +1678,9 @@ private:
string dispout = "";
bool inPct = false;
AstNode* argp = nodep->exprsp();
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
char ch = *inp; // Breaks with iterators...
string txt = nodep->text();
for (string::const_iterator it = txt.begin(); it!=txt.end(); ++it) {
char ch = *it;
if (!inPct && ch=='%') {
inPct = true;
} else if (inPct && isdigit(ch)) {

View File

@ -116,8 +116,8 @@ void V3Global::readFiles() {
V3Parse parser (v3Global.rootp(), &filter, &parseSyms);
// Read top module
for (V3StringList::const_iterator it = v3Global.opt.vFiles().begin();
it != v3Global.opt.vFiles().end(); ++it) {
const V3StringList& vFiles = v3Global.opt.vFiles();
for (V3StringList::const_iterator it = vFiles.begin(); it != vFiles.end(); ++it) {
string filename = *it;
parser.parseFile(new FileLine("COMMAND_LINE",0), filename, false,
"Cannot find file containing module: ");
@ -126,8 +126,8 @@ void V3Global::readFiles() {
// Read libraries
// To be compatible with other simulators,
// this needs to be done after the top file is read
for (V3StringSet::const_iterator it = v3Global.opt.libraryFiles().begin();
it != v3Global.opt.libraryFiles().end(); ++it) {
const V3StringSet& libraryFiles = v3Global.opt.libraryFiles();
for (V3StringSet::const_iterator it = libraryFiles.begin(); it != libraryFiles.end(); ++it) {
string filename = *it;
parser.parseFile(new FileLine("COMMAND_LINE",0), filename, true,
"Cannot find file containing library module: ");

View File

@ -17,6 +17,7 @@ if (!-r "$root/.git") {
} else {
uint();
printfll();
cstr();
}
ok(1);
@ -67,4 +68,22 @@ sub printfll {
}
}
sub cstr {
my $files = "src/*.c* src/*.h include/*.c* include/*.h test_c/*.c* test_regress/t/*.c* test_regress/t/*.h";
my $cmd = "cd $root && grep -n -P 'c_str|begin|end' $files | sort";
print "C $cmd\n";
my $grep = `$cmd`;
my %names;
foreach my $line (split /\n/, $grep) {
if ($line =~ /^([^:]+).*\(\)[a-z0-9_().->]*[.->]+(c_str|r?begin|r?end)\(\)/) {
next if $line =~ /lintok-begin-on-ref/;
print "$line\n";
$names{$1} = 1;
}
}
if (keys %names) {
$Self->error("Files with potential c_str() lifetime issue: ",join(' ',sort keys %names));
}
}
1;