mirror of
https://github.com/verilator/verilator.git
synced 2025-04-16 01:26:54 +00:00
Fix carriage-returns embedded in display formats
Internals: Store all AstDisplay etc strings in un-backslashed raw format.
This commit is contained in:
parent
996afe7d95
commit
b4d3806f10
@ -196,6 +196,31 @@ string AstNode::prettyTypeName() const {
|
||||
return string(typeName())+" '"+prettyName()+"'";
|
||||
}
|
||||
|
||||
string AstNode::quoteName(const string& namein) {
|
||||
// Encode control chars into C style escapes
|
||||
// Reverse is V3Parse::deQuote
|
||||
const char* start = namein.c_str();
|
||||
string out;
|
||||
for (const char* pos = start; *pos; pos++) {
|
||||
if (pos[0]=='\\' || pos[0]=='"') {
|
||||
out += string("\\")+pos[0];
|
||||
} else if (pos[0]=='\n') {
|
||||
out += "\\n";
|
||||
} else if (pos[0]=='\r') {
|
||||
out += "\\r";
|
||||
} else if (pos[0]=='\t') {
|
||||
out += "\\t";
|
||||
} else if (isprint(pos[0])) {
|
||||
out += pos[0];
|
||||
} else {
|
||||
// This will also cover \a etc
|
||||
char octal[10]; sprintf(octal,"\\%03o",pos[0]);
|
||||
out += octal;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int AstNode::widthPow2() const {
|
||||
// I.e. width 30 returns 32, width 32 returns 32.
|
||||
uint32_t width = this->width();
|
||||
|
@ -675,6 +675,7 @@ public:
|
||||
virtual string verilogKwd() const { return ""; }
|
||||
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
||||
static string dedotName(const string& namein); // Name with dots removed
|
||||
static string quoteName(const string& namein); // Name with control chars quoted
|
||||
static string prettyName(const string& namein); // Name for printing out to the user
|
||||
static string encodeName(const string& namein); // Encode user name into internal C representation
|
||||
static string encodeNumber(vlsint64_t numin); // Encode number into internal C representation
|
||||
|
@ -273,7 +273,7 @@ void AstNode::dump(ostream& os) {
|
||||
<<" "<<(isSigned()?"s":"")
|
||||
<<"w"<<(widthSized()?"":"u")<<width();
|
||||
if (!widthSized()) os<<"/"<<widthMin();
|
||||
if (name()!="") os<<" "<<name();
|
||||
if (name()!="") os<<" "<<AstNode::quoteName(name());
|
||||
}
|
||||
|
||||
void AstAttrOf::dump(ostream& str) {
|
||||
|
@ -227,7 +227,7 @@ public:
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
string text = nodep->text();
|
||||
if (nodep->addNewline()) text += "\\n";
|
||||
if (nodep->addNewline()) text += "\n";
|
||||
displayNode(nodep, text, nodep->exprsp(), false);
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep, AstNUser*) {
|
||||
@ -994,9 +994,7 @@ void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) {
|
||||
isStmt = true;
|
||||
nodep->v3fatalSrc("Unknown displayEmit node type");
|
||||
}
|
||||
puts("\"");
|
||||
ofp()->putsNoTracking(emitDispState.m_format); // Not putsQuoted - already contains \s
|
||||
puts("\"");
|
||||
ofp()->putsQuoted(emitDispState.m_format);
|
||||
// Arguments
|
||||
for (unsigned i=0; i < emitDispState.m_argsp.size(); i++) {
|
||||
puts(",");
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "V3Global.h"
|
||||
#include "V3File.h"
|
||||
#include "V3PreShell.h"
|
||||
#include "V3Ast.h"
|
||||
|
||||
//######################################################################
|
||||
// V3File Internal state
|
||||
@ -435,16 +436,9 @@ void V3OutFile::putsQuoted(const char* strg) {
|
||||
// Quote \ and " for use inside C programs
|
||||
// Don't use to quote a filename for #include - #include doesn't \ escape.
|
||||
putcNoTracking('"');
|
||||
for (const char* cp=strg; *cp; cp++) {
|
||||
if (*cp == '\\') {
|
||||
putcNoTracking('\\');
|
||||
putcNoTracking('\\');
|
||||
} else if (*cp == '"') {
|
||||
putcNoTracking('\\');
|
||||
putcNoTracking('"');
|
||||
} else {
|
||||
putcNoTracking (*cp);
|
||||
}
|
||||
string quoted = AstNode::quoteName(strg);
|
||||
for (const char* cp=quoted.c_str(); *cp; cp++) {
|
||||
putcNoTracking (*cp);
|
||||
}
|
||||
putcNoTracking('"');
|
||||
}
|
||||
|
@ -1677,20 +1677,20 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
||||
| yD_STOP parenE { $$ = new AstStop($1); }
|
||||
| yD_STOP '(' expr ')' { $$ = new AstStop($1); }
|
||||
//
|
||||
| yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,"", NULL,NULL); }
|
||||
| yD_DISPLAY '(' yaSTRING commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,*$3,NULL,$4); }
|
||||
| yD_WRITE '(' yaSTRING commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::WRITE, *$3,NULL,$4); }
|
||||
| yD_FDISPLAY '(' idClassSel ',' yaSTRING commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,*$5,$3,$6); }
|
||||
| yD_FWRITE '(' idClassSel ',' yaSTRING commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::WRITE, *$5,$3,$6); }
|
||||
| yD_INFO parenE { $$ = new AstDisplay($1,AstDisplayType::INFO, "", NULL,NULL); }
|
||||
| yD_INFO '(' yaSTRING commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::INFO, *$3,NULL,$4); }
|
||||
| yD_WARNING parenE { $$ = new AstDisplay($1,AstDisplayType::WARNING,"", NULL,NULL); }
|
||||
| yD_WARNING '(' yaSTRING commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::WARNING,*$3,NULL,$4); }
|
||||
| yD_ERROR parenE { $$ = V3Parse::createDisplayError($1); }
|
||||
| yD_ERROR '(' yaSTRING commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::ERROR, *$3,NULL,$4); $$->addNext(new AstStop($1)); }
|
||||
| yD_FATAL parenE { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); }
|
||||
| yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); if ($3) $3->deleteTree(); }
|
||||
| yD_FATAL '(' expr ',' yaSTRING commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::FATAL, *$5,NULL,$6); $$->addNext(new AstStop($1)); if ($3) $3->deleteTree(); }
|
||||
| yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,"", NULL,NULL); }
|
||||
| yD_DISPLAY '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,*$3,NULL,$4); }
|
||||
| yD_WRITE '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::WRITE, *$3,NULL,$4); }
|
||||
| yD_FDISPLAY '(' idClassSel ',' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::DISPLAY,*$5,$3,$6); }
|
||||
| yD_FWRITE '(' idClassSel ',' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::WRITE, *$5,$3,$6); }
|
||||
| yD_INFO parenE { $$ = new AstDisplay($1,AstDisplayType::INFO, "", NULL,NULL); }
|
||||
| yD_INFO '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::INFO, *$3,NULL,$4); }
|
||||
| yD_WARNING parenE { $$ = new AstDisplay($1,AstDisplayType::WARNING,"", NULL,NULL); }
|
||||
| yD_WARNING '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::WARNING,*$3,NULL,$4); }
|
||||
| yD_ERROR parenE { $$ = V3Parse::createDisplayError($1); }
|
||||
| yD_ERROR '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::ERROR, *$3,NULL,$4); $$->addNext(new AstStop($1)); }
|
||||
| yD_FATAL parenE { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); }
|
||||
| yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::FATAL, "", NULL,NULL); $$->addNext(new AstStop($1)); if ($3) $3->deleteTree(); }
|
||||
| yD_FATAL '(' expr ',' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::FATAL, *$5,NULL,$6); $$->addNext(new AstStop($1)); if ($3) $3->deleteTree(); }
|
||||
//
|
||||
| yD_READMEMB '(' expr ',' varRefMem ')' { $$ = new AstReadMem($1,false,$3,$5,NULL,NULL); }
|
||||
| yD_READMEMB '(' expr ',' varRefMem ',' expr ')' { $$ = new AstReadMem($1,false,$3,$5,$7,NULL); }
|
||||
@ -1711,8 +1711,8 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
||||
| yD_FEOF '(' expr ')' { $$ = new AstFEof($1,$3); }
|
||||
| yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); }
|
||||
| yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); }
|
||||
| yD_FSCANF '(' expr ',' yaSTRING commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
||||
| yD_SSCANF '(' expr ',' yaSTRING commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
||||
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
||||
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
||||
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
|
||||
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
|
||||
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
|
||||
@ -2372,6 +2372,11 @@ varRefBase<varrefp>:
|
||||
id { $$ = new AstVarRef(CRELINE(),*$1,false);}
|
||||
;
|
||||
|
||||
// yaSTRING shouldn't be used directly, instead via an abstraction below
|
||||
str<strp>: // yaSTRING but with \{escapes} need decoded
|
||||
yaSTRING { $$ = V3Read::newString(V3Parse::deQuote(CRELINE(),*$1)); }
|
||||
;
|
||||
|
||||
strAsInt<nodep>:
|
||||
yaSTRING { $$ = new AstConst(CRELINE(),V3Number(V3Number::VerilogString(),CRELINE(),V3Parse::deQuote(CRELINE(),*$1)));}
|
||||
;
|
||||
@ -2593,6 +2598,7 @@ AstVar* V3Parse::createVariable(FileLine* fileline, string name, AstRange* array
|
||||
|
||||
string V3Parse::deQuote(FileLine* fileline, string text) {
|
||||
// Fix up the quoted strings the user put in, for example "\"" becomes "
|
||||
// Reverse is AstNode::quoteName(...)
|
||||
bool quoted = false;
|
||||
string newtext;
|
||||
unsigned char octal_val = 0;
|
||||
|
@ -12,7 +12,7 @@ compile (
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>quotemeta(
|
||||
expect=>quotemeta(dequote(
|
||||
'[0] In TOP.v: Hi
|
||||
[0] In TOP.v.sub
|
||||
[0] In TOP.v.sub.subblock
|
||||
@ -26,9 +26,14 @@ execute (
|
||||
|
||||
[0] %s=! %s= what! %s= hmmm!1234
|
||||
[0] hello, from a very long string. Percent %s are literally substituted in.
|
||||
[0] Embedded <#013> return
|
||||
*-* All Finished *-*
|
||||
'),
|
||||
')),
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
||||
# Don't put control chars into our source repository, pre-compress instead
|
||||
sub dequote { my $s = shift; $s =~ s/<#013>/\r/g; $s; }
|
||||
|
||||
1;
|
||||
|
@ -37,6 +37,7 @@ module t;
|
||||
|
||||
$display("[%0t] %s%s%s", $time,
|
||||
"hel", "lo, fr", "om a very long string. Percent %s are literally substituted in.");
|
||||
$write("[%0t] Embedded \r return\n", $time);
|
||||
|
||||
// Str check
|
||||
`ifndef nc // NC-Verilog 5.3 chokes on this test
|
||||
|
@ -15,7 +15,7 @@ compile (
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
expect=>quotemeta(
|
||||
expect=>quotemeta(dequote(
|
||||
'[0] In TOP.v: Hi
|
||||
[0] In TOP.v.sub
|
||||
[0] In TOP.v.sub.subblock
|
||||
@ -29,9 +29,14 @@ execute (
|
||||
|
||||
[0] %s=! %s= what! %s= hmmm!1234
|
||||
[0] hello, from a very long string. Percent %s are literally substituted in.
|
||||
[0] Embedded <#013> return
|
||||
*-* All Finished *-*
|
||||
'),
|
||||
')),
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
||||
# Don't put control chars into our source repository, pre-compress instead
|
||||
sub dequote { my $s = shift; $s =~ s/<#013>/\r/g; $s; }
|
||||
|
||||
1;
|
||||
|
Loading…
Reference in New Issue
Block a user