Fix define formal arguments that contain newlines, bug84.

This commit is contained in:
Wilson Snyder
2009-05-11 11:57:43 -04:00
parent 96d150e92d
commit 4e522ab7f5
6 changed files with 130 additions and 39 deletions
+48 -24
View File
@@ -111,12 +111,14 @@ struct V3PreProcImp : public V3PreProc {
V3PreLex* m_lexp; // Current lexer state (NULL = closed)
stack<V3PreLex*> m_includeStack; // Stack of includers above current m_lexp
enum ProcState { ps_TOP, ps_DEFNAME, ps_DEFVALUE, ps_DEFPAREN, ps_DEFARG,
enum ProcState { ps_TOP,
ps_DEFNAME, ps_DEFFORM, ps_DEFVALUE, ps_DEFPAREN, ps_DEFARG,
ps_INCNAME, ps_ERRORNAME };
ProcState m_state; // Current state of parser
int m_stateFor; // Token state is parsing for
int m_off; // If non-zero, ifdef level is turned off, don't dump text
string m_lastSym; // Last symbol name found.
string m_formals; ///< Last formals found
// For getRawToken/ `line insertion
string m_lineCmt; // Line comment(s) to be returned
@@ -371,6 +373,7 @@ const char* V3PreProcImp::tokenName(int tok) {
case VP_LINE : return("LINE");
case VP_SYMBOL : return("SYMBOL");
case VP_STRING : return("STRING");
case VP_DEFFORM : return("DEFFORM");
case VP_DEFVALUE : return("DEFVALUE");
case VP_COMMENT : return("COMMENT");
case VP_TEXT : return("TEXT");
@@ -581,7 +584,7 @@ int V3PreProcImp::getRawToken() {
return (VP_TEXT);
}
if (m_lineCmt!="") {
// We have some `line directive to return to the user. Do it.
// We have some `line directive or other processed data to return to the user.
static string rtncmt; // Keep the c string till next call
rtncmt = m_lineCmt;
if (m_lineCmtNl) {
@@ -591,10 +594,11 @@ int V3PreProcImp::getRawToken() {
yytext=(char*)rtncmt.c_str(); yyleng=rtncmt.length();
m_lineCmt = "";
if (yyleng) m_rawAtBol = (yytext[yyleng-1]=='\n');
if (m_state!=ps_DEFVALUE) return (VP_TEXT);
else {
if (m_state==ps_DEFVALUE) {
V3PreLex::s_currentLexp->appendDefValue(yytext,yyleng);
goto next_tok;
} else {
return (VP_TEXT);
}
}
if (isEof()) return (VP_EOF);
@@ -609,9 +613,9 @@ int V3PreProcImp::getRawToken() {
string::size_type pos;
while ((pos=buf.find("\n")) != string::npos) { buf.replace(pos, 1, "\\n"); }
while ((pos=buf.find("\r")) != string::npos) { buf.replace(pos, 1, "\\r"); }
fprintf (stderr, "%d: RAW %s s%d dr%d: %-10s: %s\n",
fprintf (stderr, "%d: RAW %s s%d dr%d: <%d>%-10s: %s\n",
fileline()->lineno(), m_off?"of":"on", m_state, (int)m_defRefs.size(),
tokenName(tok), buf.c_str());
m_lexp->currentStartState(), tokenName(tok), buf.c_str());
}
// On EOF, try to pop to upper level includes, as needed.
@@ -695,8 +699,8 @@ int V3PreProcImp::getToken() {
}
else if (m_stateFor==VP_DEFINE) {
// m_lastSym already set.
m_state = ps_DEFVALUE;
m_lexp->pushStateDefValue();
m_state = ps_DEFFORM;
m_lexp->pushStateDefForm();
}
else fileline()->v3fatalSrc("Bad case\n");
goto next_tok;
@@ -706,45 +710,64 @@ int V3PreProcImp::getToken() {
goto next_tok;
}
}
case ps_DEFFORM: {
if (tok==VP_DEFFORM) {
m_formals = m_lexp->m_defValue;
m_state = ps_DEFVALUE;
if (debug()) cout<<"DefFormals='"<<m_formals<<"'\n";
m_lexp->pushStateDefValue();
goto next_tok;
} else if (tok==VP_TEXT) {
// IE, something like comment in formals
if (!m_off) return tok;
else goto next_tok;
} else {
fileline()->v3error("Expecting define formal arguments. Found: "<<tokenName(tok));
goto next_tok;
}
}
case ps_DEFVALUE: {
static string newlines;
newlines = "\n"; // Always start with trailing return
if (tok == VP_DEFVALUE) {
if (debug()) cout<<"DefValue='"<<m_lexp->m_defValue<<"' formals='"<<m_formals<<"'\n";
// Add any formals
string formAndValue = m_formals + m_lexp->m_defValue;
// Remove returns
for (unsigned i=0; i<m_lexp->m_defValue.length(); i++) {
if (m_lexp->m_defValue[i] == '\n') {
m_lexp->m_defValue[i] = ' ';
for (unsigned i=0; i<formAndValue.length(); i++) {
if (formAndValue[i] == '\n') {
formAndValue[i] = ' ';
newlines += "\n";
}
}
if (!m_off) {
string params;
if (m_lexp->m_defValue=="" || isspace(m_lexp->m_defValue[0])) {
if (formAndValue=="" || isspace(formAndValue[0])) {
// Define without parameters
} else if (m_lexp->m_defValue[0] == '(') {
string::size_type paren = m_lexp->m_defValue.find(")");
} else if (formAndValue[0] == '(') {
string::size_type paren = formAndValue.find(")");
if (paren == string::npos) {
fileline()->v3error("Missing ) to end define arguments.");
} else {
params = m_lexp->m_defValue.substr(0, paren+1);
m_lexp->m_defValue.replace(0, paren+1, "");
params = formAndValue.substr(0, paren+1);
formAndValue.replace(0, paren+1, "");
}
} else {
fileline()->v3error("Missing space or paren to start define value.");
}
// Remove leading whitespace
unsigned leadspace = 0;
while (m_lexp->m_defValue.length() > leadspace
&& isspace(m_lexp->m_defValue[leadspace])) leadspace++;
if (leadspace) m_lexp->m_defValue.erase(0,leadspace);
while (formAndValue.length() > leadspace
&& isspace(formAndValue[leadspace])) leadspace++;
if (leadspace) formAndValue.erase(0,leadspace);
// Remove trailing whitespace
unsigned trailspace = 0;
while (m_lexp->m_defValue.length() > trailspace
&& isspace(m_lexp->m_defValue[m_lexp->m_defValue.length()-1-trailspace])) trailspace++;
if (trailspace) m_lexp->m_defValue.erase(m_lexp->m_defValue.length()-trailspace,trailspace);
while (formAndValue.length() > trailspace
&& isspace(formAndValue[formAndValue.length()-1-trailspace])) trailspace++;
if (trailspace) formAndValue.erase(formAndValue.length()-trailspace,trailspace);
// Define it
UINFO(4,"Define "<<m_lastSym<<" = '"<<m_lexp->m_defValue<<"'"<<endl);
define(fileline(), m_lastSym, m_lexp->m_defValue, params);
UINFO(4,"Define "<<m_lastSym<<" = '"<<formAndValue<<"'"<<endl);
define(fileline(), m_lastSym, formAndValue, params);
}
} else {
fileline()->v3fatalSrc("Bad define text\n");
@@ -954,6 +977,7 @@ int V3PreProcImp::getToken() {
}
case VP_WHITE: // Handled at top of loop
case VP_COMMENT: // Handled at top of loop
case VP_DEFFORM: // Handled by m_state=ps_DEFFORM;
case VP_DEFVALUE: // Handled by m_state=ps_DEFVALUE;
default:
fileline()->v3fatalSrc("Internal error: Unexpected token.\n");