int V3PreProcImp::getFinalToken(string& buf) { // Return the next user-visible token in the input stream. // Includes and such are handled here, and are never seen by the caller. if (!m_finAhead) { m_finAhead = true; m_finToken = getStateToken(); m_finBuf = string (yyourtext(), yyourleng()); } int tok = m_finToken; buf = m_finBuf; 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++; if ((tok == VP_TEXT || tok == VP_LINE) && 0==strncmp(bufp,"`line ",6)) { int enter; m_finFilelinep->lineDirective(bufp, enter/*ref*/); } else { if (m_finAtBol && !(tok==VP_TEXT && buf=="\n") && m_preprocp->lineDirectives()) { if (int outBehind = m_lexp->m_tokFilelinep->lineno() - m_finFilelinep->lineno()) { if (debug()>=5) fprintf(stderr,"%d: FIN: readjust, fin at %d request at %d\n", m_lexp->m_tokFilelinep->lineno(), m_finFilelinep->lineno(), m_lexp->m_tokFilelinep->lineno()); m_finFilelinep = m_finFilelinep->create(m_lexp->m_tokFilelinep->filename(),m_lexp->m_tokFilelinep->lineno()); if (outBehind > 0 && outBehind <= (int)V3PreProc::NEWLINES_VS_TICKLINE) { // Output stream is behind, send newlines to get back in sync // (Most likely because we're completing a disabled `endif) if (m_preprocp->keepWhitespace()) { buf = string(outBehind,'\n'); return VP_TEXT; } } else { // Need to backup, use `line buf = m_finFilelinep->lineDirectiveStrg(0); return VP_LINE; } } } // Track newlines in prep for next token 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. } else { m_finAtBol = false; } } } m_finAhead = false; // Consumed the token return tok; }
void V3PreProcImp::openFile(FileLine* fl, V3InFilter* filterp, const string& filename) { // Open a new file, possibly overriding the current one which is active. V3File::addSrcDepend(filename); // Read a list<string> with the whole file. StrList wholefile; bool ok = filterp->readWholefile(filename, wholefile/*ref*/); if (!ok) { error("File not found: "+filename+"\n"); return; } if (!m_preprocp->isEof()) { // IE not the first file. // We allow the same include file twice, because occasionally it pops // up, with guards preventing a real recursion. if (m_lexp->m_streampStack.size()>V3PreProc::INCLUDE_DEPTH_MAX) { error("Recursive inclusion of file: "+filename); return; } // There's already a file active. Push it to work on the new one. addLineComment(0); } // Create new stream structure m_lexp->scanNewFile(m_preprocp->fileline()->create(filename, 1)); addLineComment(1); // Enter // Filter all DOS CR's en-mass. This avoids bugs with lexing CRs in the wrong places. // This will also strip them from strings, but strings aren't supposed to be multi-line without a "\" for (StrList::iterator it=wholefile.begin(); it!=wholefile.end(); ++it) { // We don't end-loop at \0 as we allow and strip mid-string '\0's (for now). bool strip = false; const char* sp = it->data(); const char* ep = sp + it->length(); // Only process if needed, as saves extra string allocations for (const char* cp=sp; cp<ep; cp++) { if (VL_UNLIKELY(*cp == '\r' || *cp == '\0')) { strip = true; break; } } if (strip) { string out; out.reserve(it->length()); for (const char* cp=sp; cp<ep; cp++) { if (!(*cp == '\r' || *cp == '\0')) { out += *cp; } } *it = out; } // Push the data to an internal buffer. m_lexp->scanBytesBack(*it); // Reclaim memory; the push saved the string contents for us *it = ""; } }
void configure(FileLine* filelinep) { // configure() separate from constructor to avoid calling abstract functions m_preprocp = this; // Silly, but to make code more similar to Verilog-Perl m_finFilelinep = filelinep->create(1); // Create lexer m_lexp = new V3PreLex (this, filelinep); m_lexp->m_keepComments = m_preprocp->keepComments(); m_lexp->m_keepWhitespace = m_preprocp->keepWhitespace(); m_lexp->m_pedantic = m_preprocp->pedantic(); m_lexp->debug(debug()>=5 ? debug() : 0); // See also V3PreProc::debug() method }
bool preprocOpen (FileLine* fl, V3InFilter* filterp, const string& modname, const string& errmsg) { // Error message or "" to suppress // Returns true if successful // Allow user to put `defined names on the command line instead of filenames, // then convert them properly. string ppmodname = s_preprocp->removeDefines (modname); // Open include or master file string filename = v3Global.opt.filePath (fl, ppmodname, errmsg); if (filename=="") return false; // Not found UINFO(2," Reading "<<filename<<endl); s_preprocp->openFile(fl, filterp, filename); return true; }
void boot(char** env) { // Create the implementation pointer if (env) {} if (!s_preprocp) { FileLine* cmdfl = new FileLine("COMMAND_LINE",0); s_preprocp = V3PreProc::createPreProc(cmdfl); s_preprocp->debug(debug()); // Default defines FileLine* prefl = new FileLine("INTERNAL_VERILATOR_DEFINE",0); s_preprocp->defineCmdLine(prefl,"VERILATOR", "1"); // LEAK_OK s_preprocp->defineCmdLine(prefl,"verilator", "1"); // LEAK_OK s_preprocp->defineCmdLine(prefl,"verilator3", "1"); // LEAK_OK s_preprocp->defineCmdLine(prefl,"systemc_clock", "/*verilator systemc_clock*/"); // LEAK_OK s_preprocp->defineCmdLine(prefl,"coverage_block_off", "/*verilator coverage_block_off*/"); // LEAK_OK } }
static int debug(bool reset=false) { static int level = -1; if (VL_UNLIKELY(level < 0) || reset) { level = v3Global.opt.debugSrcLevel(__FILE__); if (s_preprocp) s_preprocp->debug(debug()); } return level; }
bool preproc (FileLine* fl, const string& modname, V3InFilter* filterp, V3ParseImp* parsep, const string& errmsg) { // "" for no error debug(true); // Recheck if debug on - first check was before command line passed // Preprocess the given module, putting output in vppFilename UINFONL(1," Preprocessing "<<modname<<endl); // Preprocess s_filterp = filterp; bool ok = preprocOpen(fl, s_filterp, modname, errmsg); if (!ok) return false; while (!s_preprocp->isEof()) { string line = s_preprocp->getline(); V3Parse::ppPushText(parsep, line); } return true; }
void boot(char** env) { // Create the implementation pointer if (env) {} if (!s_preprocp) { FileLine* cmdfl = new FileLine("COMMAND_LINE",0); s_preprocp = V3PreProc::createPreProc(cmdfl); s_preprocp->debug(debug()); // Default defines FileLine* prefl = new FileLine("INTERNAL_VERILATOR_DEFINE",0); s_preprocp->defineCmdLine(prefl,"VERILATOR", "1"); // LEAK_OK s_preprocp->defineCmdLine(prefl,"verilator", "1"); // LEAK_OK s_preprocp->defineCmdLine(prefl,"verilator3", "1"); // LEAK_OK s_preprocp->defineCmdLine(prefl,"systemc_clock", "/*verilator systemc_clock*/"); // LEAK_OK s_preprocp->defineCmdLine(prefl,"coverage_block_off", "/*verilator coverage_block_off*/"); // LEAK_OK if (prefl->language().systemVerilog()) { // Synthesis compatibility s_preprocp->defineCmdLine(prefl,"SYSTEMVERILOG", "1"); // LEAK_OK // IEEE predefined s_preprocp->defineCmdLine(prefl,"SV_COV_START", "0"); s_preprocp->defineCmdLine(prefl,"SV_COV_STOP", "1"); s_preprocp->defineCmdLine(prefl,"SV_COV_RESET", "2"); s_preprocp->defineCmdLine(prefl,"SV_COV_CHECK", "3"); s_preprocp->defineCmdLine(prefl,"SV_COV_MODULE", "10"); s_preprocp->defineCmdLine(prefl,"SV_COV_HIER", "11"); s_preprocp->defineCmdLine(prefl,"SV_COV_ASSERTION", "20"); s_preprocp->defineCmdLine(prefl,"SV_COV_FSM_STATE", "21"); s_preprocp->defineCmdLine(prefl,"SV_COV_STATEMENT", "22"); s_preprocp->defineCmdLine(prefl,"SV_COV_TOGGLE", "23"); s_preprocp->defineCmdLine(prefl,"SV_COV_OVERFLOW", "-2"); s_preprocp->defineCmdLine(prefl,"SV_COV_ERROR", "-1"); s_preprocp->defineCmdLine(prefl,"SV_COV_NOCOV", "0"); s_preprocp->defineCmdLine(prefl,"SV_COV_OK", "1"); s_preprocp->defineCmdLine(prefl,"SV_COV_PARTIAL", "2"); } } }