Fix expansion of back-slashed escaped macros, bug441.
This commit is contained in:
parent
2be6699a6a
commit
f540362e36
4
Changes
4
Changes
|
|
@ -12,7 +12,9 @@ indicates the contributor was also the author of the fix; Thanks!
|
|||
|
||||
*** Support arrayed SystemC I/O pins. [Christophe Joly]
|
||||
|
||||
**** Fix core dump with over 100 deep UNOPTFLAT, bug432. [Joe Eiler]
|
||||
**** Fix expansion of back-slashed escaped macros, bug441. [Alberto Del Rio]
|
||||
|
||||
**** Fix core dump with over 100 deep UNOPTFLAT, bug432. [Joe Eiler]
|
||||
|
||||
**** Fix false command not found warning in makefiles. [Ruben Diez]
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ quote [\"]
|
|||
tickquote [`][\"]
|
||||
backslash [\\]
|
||||
/* Where we use symb/symbdef, we must also look for a `` join */
|
||||
/* Note in the preprocessor \ESCaped is *not* always special; mantis1537/bug441 */
|
||||
symb ([a-zA-Z_][a-zA-Z0-9_$]*|\\[^ \t\f\r\n]+)
|
||||
symbdef ([a-zA-Z_][a-zA-Z0-9_$]*|\\[^ \t\f\r\n`]+)
|
||||
word [a-zA-Z0-9_]+
|
||||
|
|
|
|||
|
|
@ -628,16 +628,18 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) {
|
|||
string argName;
|
||||
string prev;
|
||||
bool quote = false;
|
||||
bool backslashesc = false; // In \.....{space} block
|
||||
// Note we go through the loop once more at the NULL end-of-string
|
||||
for (const char* cp=value.c_str(); (*cp) || argName!=""; cp=(*cp?cp+1:cp)) {
|
||||
//cout << "CH "<<*cp<<" an "<<argName<<"\n";
|
||||
if (!quote) {
|
||||
if ( isalpha(*cp) || *cp=='_'
|
||||
|| *cp=='$' // Won't replace system functions, since no $ in argValueByName
|
||||
|| (argName!="" && (isdigit(*cp) || *cp=='$'))) {
|
||||
argName += *cp;
|
||||
continue;
|
||||
}
|
||||
//UINFO(4, "CH "<<*cp<<" an "<<argName<<endl);
|
||||
if (!quote && *cp == '\\') { backslashesc = true; }
|
||||
else if (isspace(*cp)) { backslashesc = false; }
|
||||
// We don't check for quotes; some simulators expand even inside quotes
|
||||
if ( isalpha(*cp) || *cp=='_'
|
||||
|| *cp=='$' // Won't replace system functions, since no $ in argValueByName
|
||||
|| (argName!="" && (isdigit(*cp) || *cp=='$'))) {
|
||||
argName += *cp;
|
||||
continue;
|
||||
}
|
||||
if (argName != "") {
|
||||
// Found a possible variable substitution
|
||||
|
|
@ -654,7 +656,11 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) {
|
|||
if (!quote) {
|
||||
// Check for `` only after we've detected end-of-argname
|
||||
if (cp[0]=='`' && cp[1]=='`') {
|
||||
out += "``"; // `` must get removed later, as `FOO```BAR must pre-expand FOO and BAR
|
||||
if (backslashesc) {
|
||||
// Don't put out the ``, we're forming an escape which will not expand further later
|
||||
} else {
|
||||
out += "``"; // `` must get removed later, as `FOO```BAR must pre-expand FOO and BAR
|
||||
}
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -685,12 +691,18 @@ string V3PreProcImp::defineSubst(V3DefineRef* refp) {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if (cp[0]=='\\' && cp[1]) {
|
||||
if (cp[0]=='\\' && cp[1]=='\"') {
|
||||
out += cp[0]; // \{any} Put out literal next character
|
||||
out += cp[1];
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
else if (cp[0]=='\\') {
|
||||
// Normally \{any} would put out literal next character
|
||||
// Instead we allow "`define A(nm) \nm" to expand, per proposed mantis1537
|
||||
out += cp[0];
|
||||
continue;
|
||||
}
|
||||
if (*cp=='"') quote=!quote;
|
||||
if (*cp) out += *cp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ firstline comma","line LLZZ firstline comma","line
|
|||
|
||||
`line 71 "t/t_preproc.v" 0
|
||||
|
||||
x y LLZZ "a" y
|
||||
x y LLZZ "x" y
|
||||
|
||||
`line 74 "t/t_preproc.v" 0
|
||||
|
||||
|
|
@ -398,7 +398,7 @@ x,y)--bee submacro has comma paren
|
|||
|
||||
|
||||
|
||||
$display("bits %d %d", $bits(foo), `10);
|
||||
$display("10 %d %d", $bits(foo), 10);
|
||||
|
||||
`line 260 "t/t_preproc.v" 0
|
||||
|
||||
|
|
@ -709,5 +709,86 @@ module a_b ; endmodule
|
|||
|
||||
integer foo;
|
||||
|
||||
|
||||
module t;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
`line 457 "t/t_preproc.v" 2
|
||||
initial begin : \`LEX_CAT(a[0],_assignment)
|
||||
`line 464 "t/t_preproc.v" 0
|
||||
$write("GOT%%m='%m' EXP='%s'\n", "t.\\`LEX_CAT(a[0],_assignment) "); end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
initial begin : \a[0]_assignment_a[1]
|
||||
`line 471 "t/t_preproc.v" 0
|
||||
$write("GOT%%m='%m' EXP='%s'\n", "t.\\a[0]_assignment_a[1] "); end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
initial begin : \`CAT(pp,suffix) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(pp,suffix) "); end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
initial begin : \`CAT(ff,bb)
|
||||
`line 485 "t/t_preproc.v" 0
|
||||
$write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(ff,bb) "); end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
initial begin : \`zzz
|
||||
`line 491 "t/t_preproc.v" 0
|
||||
$write("GOT%%m='%m' EXP='%s'\n", "t.\\`zzz "); end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
initial begin : \`FOO
|
||||
`line 498 "t/t_preproc.v" 0
|
||||
$write("GOT%%m='%m' OTHER_EXP='%s'\n OUR_EXP='%s'", "t.bar ","t.\\`FOO "); end
|
||||
|
||||
initial begin : \xx`FOO
|
||||
`line 500 "t/t_preproc.v" 0
|
||||
$write("GOT%%m='%m' EXP='%s'\n", "t.\\xx`FOO "); end
|
||||
|
||||
|
||||
|
||||
|
||||
initial begin : \`UNKNOWN $write("GOT%%m='%m' EXP='%s'\n", "t.\\`UNKNOWN "); end
|
||||
|
||||
|
||||
|
||||
initial begin : \`DEF_NO_EXPAND $write("GOT%%m='%m' EXP='%s'\n", "t.\\`DEF_NO_EXPAND "); end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
initial $write("GOT='%s' EXP='%s'\n", "foo bar baz", "foo bar baz");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
initial $write("GOT='%s' EXP='%s'\n", "foo `A(bar) baz", "foo `A(bar) baz");
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
`line 526 "t/t_preproc.v" 2
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ Line_Preproc_Check `__LINE__
|
|||
comma","line)
|
||||
|
||||
`define withquote(a, bar) a bar LLZZ "a" bar
|
||||
`withquote( x , y)
|
||||
`withquote( x , y) // Simulators disagree here; some substitute "a" others do not
|
||||
|
||||
`define noparam (a,b)
|
||||
`noparam(a,b)
|
||||
|
|
@ -254,7 +254,7 @@ Not a \`define
|
|||
|
||||
//======================================================================
|
||||
// bug191
|
||||
`define bug191(bits) $display("bits %d %d", $bits(foo), `bits);
|
||||
`define bug191(bits) $display("bits %d %d", $bits(foo), bits);
|
||||
`bug191(10)
|
||||
|
||||
//======================================================================
|
||||
|
|
@ -453,3 +453,72 @@ module `Q1 ; endmodule
|
|||
// bug311
|
||||
integer/*NEED_SPACE*/foo;
|
||||
//======================================================================
|
||||
// bug441
|
||||
module t;
|
||||
//-----
|
||||
// case provided
|
||||
// note this does NOT escape as suggested in the mail
|
||||
`define LEX_CAT(lexem1, lexem2) lexem1``lexem2
|
||||
`define LEX_ESC(name) \name \
|
||||
|
||||
initial begin : `LEX_ESC( `LEX_CAT(a[0],_assignment) ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`LEX_CAT(a[0],_assignment) "); end
|
||||
//-----
|
||||
// SHOULD(simulator-dependant): Backslash doesn't prevent arguments from
|
||||
// substituting and the \ staying in the expansion
|
||||
// Note space after name is important so when substitute it has ending whitespace
|
||||
`define ESC_CAT(name,name2) \name``_assignment_``name2 \
|
||||
|
||||
initial begin : `ESC_CAT( a[0],a[1] ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\a[0]_assignment_a[1] "); end
|
||||
`undef ESC_CAT
|
||||
//-----
|
||||
`define CAT(a,b) a``b
|
||||
`define ESC(name) \`CAT(name,suffix)
|
||||
// RULE: Ignoring backslash does NOT allow an additional expansion level
|
||||
// (Because ESC gets expanded then the \ has it's normal escape meaning)
|
||||
initial begin : `ESC(pp) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(pp,suffix) "); end
|
||||
`undef CAT `undef ESC
|
||||
//-----
|
||||
`define CAT(a,b) a``b
|
||||
`define ESC(name) \name \
|
||||
|
||||
// Similar to above; \ does not allow expansion after substitution
|
||||
initial begin : `ESC( `CAT(ff,bb) ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(ff,bb) "); end
|
||||
`undef CAT `undef ESC
|
||||
//-----
|
||||
`define ESC(name) \name \
|
||||
|
||||
// MUST: Unknown macro with backslash escape stays as escaped symbol name
|
||||
initial begin : `ESC( `zzz ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`zzz "); end
|
||||
`undef ESC
|
||||
//-----
|
||||
`define FOO bar
|
||||
`define ESC(name) \name \
|
||||
|
||||
// SHOULD(simulator-dependant): Known macro with backslash escape expands
|
||||
initial begin : `ESC( `FOO ) $write("GOT%%m='%m' OTHER_EXP='%s'\n OUR_EXP='%s'", "t.bar ","t.\\`FOO "); end
|
||||
// SHOULD(simulator-dependant): Prefix breaks the above
|
||||
initial begin : `ESC( xx`FOO ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\xx`FOO "); end
|
||||
`undef FOO `undef ESC
|
||||
//-----
|
||||
// MUST: Unknown macro not under call with backslash escape doesn't expand
|
||||
`undef UNKNOWN
|
||||
initial begin : \`UNKNOWN $write("GOT%%m='%m' EXP='%s'\n", "t.\\`UNKNOWN "); end
|
||||
//-----
|
||||
// MUST: Unknown macro not under call doesn't expand
|
||||
`define DEF_NO_EXPAND error_dont_expand
|
||||
initial begin : \`DEF_NO_EXPAND $write("GOT%%m='%m' EXP='%s'\n", "t.\\`DEF_NO_EXPAND "); end
|
||||
`undef DEF_NO_EXPAND
|
||||
//-----
|
||||
// bug441 derivative
|
||||
// SHOULD(simulator-dependant): Quotes doesn't prevent arguments from expanding (like backslashes above)
|
||||
`define STR(name) "foo name baz"
|
||||
initial $write("GOT='%s' EXP='%s'\n", `STR(bar), "foo bar baz");
|
||||
`undef STR
|
||||
//-----
|
||||
// RULE: Because there are quotes after substituting STR, the `A does NOT expand
|
||||
`define STR(name) "foo name baz"
|
||||
`define A(name) boo name hiss
|
||||
initial $write("GOT='%s' EXP='%s'\n", `STR(`A(bar)), "foo `A(bar) baz");
|
||||
`undef A `undef STR
|
||||
endmodule
|
||||
//======================================================================
|
||||
|
|
|
|||
Loading…
Reference in New Issue