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
    }
예제 #4
0
    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;
    }
예제 #5
0
    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
	}
    }
예제 #6
0
    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;
    }
예제 #7
0
    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;
    }
예제 #8
0
    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");
	    }
	}
    }