Commit 47f3c595 authored by mk's avatar mk
Browse files

some changes

parent 85c46d2a
Loading
Loading
Loading
Loading

src/VFileLine.cpp

0 → 100644
+114 −0
Original line number Diff line number Diff line
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2000-2013 by Wilson Snyder.  This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
//*************************************************************************
/// \file
/// \brief Verilog::Preproc: Error handling implementation
///
/// Authors: Wilson Snyder
///
/// Code available from: http://www.veripool.org/verilog-perl
///
//*************************************************************************

#include <cstdio>
#include <cstdlib>

#include "VFileLine.h"

int VFileLine::s_numErrors = 0;		///< Number of errors detected

//============================================================================

void VFileLine::init(const string& filename, int lineno) {
    m_filename = filename;
    m_lineno = lineno;
}

const string VFileLine::filebasename () const {
    string name = filename();
    string::size_type slash;
    if ((slash = name.rfind("/")) != string::npos) {
	name.erase(0,slash+1);
    }
    return name;
}

void VFileLine::fatal(const string& msg) {
    error(msg);
    error("Fatal Error detected");
    abort();
}
void VFileLine::error(const string& msg) {
    VFileLine::s_numErrors++;
    if (msg[msg.length()-1] != '\n') {
	fprintf (stderr, "%%Error: %s", msg.c_str());
    } else {
	fprintf (stderr, "%%Error: %s\n", msg.c_str());	// Append newline, as user omitted it.
    }
}

const char* VFileLine::itoa(int i) {
    static char buf[100];
    sprintf(buf,"%d",i);
    return buf;
}

string VFileLine::lineDirectiveStrg(int enterExit) const {
    char numbuf[20]; sprintf(numbuf, "%d", lineno());
    char levelbuf[20]; sprintf(levelbuf, "%d", enterExit);
    return ((string)"// `line first "+numbuf+" \""+filename()+"\" "+levelbuf+"\n");
}

VFileLine* VFileLine::lineDirective(const char* textp, int& enterExitRef) {
    // Handle `line directive
    // Skip `line
    while (*textp && isspace(*textp)) textp++;
    while (*textp && !isspace(*textp)) textp++;
    while (*textp && (isspace(*textp) || *textp=='"')) textp++;

    // Grab linenumber
    int lineno = this->lineno();
    const char *ln = textp;
    while (*textp && !isspace(*textp)) textp++;
    if (isdigit(*ln)) {
	lineno = atoi(ln);
    }
    while (*textp && (isspace(*textp) || *textp=='"')) textp++;

    // Grab filename
    string filename = this->filename();
    const char* fn = textp;
    while (*textp && !(isspace(*textp) || *textp=='"')) textp++;
    if (textp != fn) {
	string strfn = fn;
	strfn = strfn.substr(0, textp-fn);
	filename = strfn;
    }

    // Grab level
    while (*textp && (isspace(*textp) || *textp=='"')) textp++;
    if (isdigit(*textp)) enterExitRef = atoi(textp);
    else enterExitRef = 0;

    return create(filename,lineno);
}

//======================================================================
// Global scope

ostream& operator<<(ostream& os, VFileLine* flp) {
    if (flp->filename()!="") {
	os <<flp->filename()<<":"<<dec<<flp->lineno()<<": "<<hex;
    }
    return(os);
}

src/VFileLine.h

0 → 100644
+105 −0
Original line number Diff line number Diff line
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2000-2013 by Wilson Snyder.  This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
//*************************************************************************
/// \file
/// \brief Verilog::Preproc: Error handling
///
/// Authors: Wilson Snyder
///
/// Code available from: http://www.veripool.org/verilog-perl
///
//*************************************************************************

#ifndef _VFILELINE_H_
#define _VFILELINE_H_ 1
#include <string>
#include <iostream>
#include <sstream>
using namespace std;

//============================================================================
// VFileLine
/// User information and error reporting functions
////
/// Users can override this class to implement their own error handling

class VFileLine {
private:
    int		m_lineno;		///< Line number in file
    string	m_filename;		///< File name
    static int	s_numErrors;		///< Number of errors detected

protected:
    VFileLine(int called_only_for_default) {init("",0);}

public:
    // CONSTRUCTORS
    /// Create a new fileline, for a new file and/or line number.
    /// Member functions, so that if a user provides another class, a change in the
    /// filename/linenumber will create a new element using the derived class.
    virtual VFileLine* create(const string& filename, int lineno) = 0;
    /// Create with same filename, new line number; just calls create(fn,ln)
    virtual VFileLine* create(int lineno)
     { 
      return create(filename(), lineno); 
      }
    virtual void init(const string& filename, int lineno);
    virtual ~VFileLine() {}
    // ACCESSORS
    int lineno () const { return m_lineno; }	///< Return line number
    void linenoIncInPlace() { m_lineno++; }	///< Increment line IN PLACE; normally use create() instead
    const string filename () const { return m_filename; }	///< Return filename
    const string filebasename () const;	///< Filename with any directory stripped
    string lineDirectiveStrg(int enter_exit_level) const;
    // METHODS
    virtual void fatal(const string& msg);	///< Report a fatal error at given location
    virtual void error(const string& msg);	///< Report a error at given location
    VFileLine* lineDirective(const char* textp, int& enterExitRef);
    // STATIC METHODS
    static int numErrors() {return s_numErrors;}	///< Return total errors detected

    // Internal methods -- special use
    static const char* itoa(int i);	///< Internal: Not reentrant! - for fatalSrc() only
};

ostream& operator<<(ostream& os, VFileLine* fileline);

/// Use this instead of fatal() to mention the source code line.
#define fatalSrc(msg) fatal((string)"Internal Error: "+__FILE__+":"+VFileLine::itoa(__LINE__)+": "+(msg))

template< class T> std::string cvtToStr (const T& t) {
    ostringstream os; os<<t; return os.str();
}


class VerilogFileLine : public VFileLine
{
 
 public:
    VerilogFileLine(const string& file,int line):VFileLine(0)
    {
      init(file,line);
    }
 
 virtual VFileLine* create(const string& filename, int lineno)
 {
 VerilogFileLine* fnew=new VerilogFileLine(filename,lineno);
 return fnew;
 }
 
    /// Create with same filename, new line number; just calls create(fn,ln)
 virtual VFileLine* create(int lineno) { return create(filename(), lineno); }

};

#endif // Guard

src/VPreLex.cpp

0 → 100644
+3020 −0

File added.

Preview size limit exceeded, changes collapsed.

src/VPreLex.h

0 → 100644
+249 −0
Original line number Diff line number Diff line
// -*- C++ -*-
//*************************************************************************
//
// Copyright 2000-2013 by Wilson Snyder.  This program is free software;
// you can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
//*************************************************************************
/// \file
/// \brief Verilog::Preproc: Internal header for lex interfacing
///
/// Authors: Wilson Snyder
///
/// Code available from: http://www.veripool.org/verilog-perl
///
/// This header provides the interface between the lex proper VPreLex.l/.cpp
/// and the class implementation file VPreProc.cpp
/// It is not intended for user applications.
///
//*************************************************************************

#ifndef _VPREPROCLEX_H_		// Guard
#define _VPREPROCLEX_H_ 1

#include <deque>
#include <stack>

#include "VFileLine.h"
#include "VPreProc.h"

class VPreLex;
struct VPreProcImp;

//======================================================================
// Token codes
// If changing, see VPreProc.cpp's VPreProcImp::tokenName()
#define VP_EOF		0

#define VP_INCLUDE	256
#define VP_IFDEF	257
#define VP_IFNDEF	258
#define VP_ENDIF	259
#define VP_UNDEF	260
#define VP_DEFINE	261
#define VP_ELSE		262
#define VP_ELSIF	263
#define VP_LINE		264
#define VP_UNDEFINEALL	265

#define VP_SYMBOL	300
#define VP_STRING	301
#define VP_DEFVALUE	302
#define VP_COMMENT	303
#define VP_TEXT		304
#define VP_WHITE	305
#define VP_DEFREF	306
#define VP_DEFARG	307
#define VP_ERROR	308
#define VP_DEFFORM	309
#define VP_STRIFY	310
#define VP_BACKQUOTE	311
#define VP_SYMBOL_JOIN	312
#define VP_DEFREF_JOIN	313

#define VP_PSL		350

//======================================================================
// Externs created by flex
// We add a prefix so that other lexers/flexers in the same program won't collide.
#ifndef yy_create_buffer
# define yy_create_buffer VPreLex_create_buffer
# define yy_delete_buffer VPreLex_delete_buffer
# define yy_scan_buffer VPreLex_scan_buffer
# define yy_scan_string VPreLex_scan_string
# define yy_scan_bytes VPreLex_scan_bytes
# define yy_flex_debug VPreLex_flex_debug
# define yy_init_buffer VPreLex_init_buffer
# define yy_flush_buffer VPreLex_flush_buffer
# define yy_load_buffer_state VPreLex_load_buffer_state
# define yy_switch_to_buffer VPreLex_switch_to_buffer
# define yyin VPreLexin
# define yyleng VPreLexleng
# define yylex VPreLexlex
# define yyout VPreLexout
# define yyrestart VPreLexrestart
# define yytext VPreLextext
#endif

#ifndef yyourleng
# define yyourleng VPreLexourleng
# define yyourtext VPreLexourtext
#endif

#ifndef YY_BUFFER_STATE
struct yy_buffer_state;
typedef struct yy_buffer_state *YY_BUFFER_STATE;
# define YY_BUF_SIZE 16384
#endif

extern int yylex();
extern void yyrestart(FILE*);

// Accessors, because flex keeps changing the type of yyleng
extern char* yyourtext();
extern size_t yyourleng();
extern void yyourtext(const char* textp, size_t size);  // Must call with static

YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size );
void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer );
void yy_delete_buffer( YY_BUFFER_STATE b );

//======================================================================

#define KEEPCMT_SUB 2
#define KEEPCMT_EXP 3

//======================================================================
// Entry for each file processed; a stack of entries included

class VPreStream {
public:
    VFileLine*		m_curFilelinep;	// Current processing point (see also m_tokFilelinep)
    VPreLex*		m_lexp;		// Lexer, for resource tracking
    deque<string>	m_buffers;	// Buffer of characters to process
    int			m_ignNewlines;	// Ignore multiline newlines
    bool		m_eof;		// "EOF" buffer
    bool		m_file;		// Buffer is start of new file
    int			m_termState;	// Termination fsm
    VPreStream(VFileLine* fl, VPreLex* lexp)
	: m_curFilelinep(fl), m_lexp(lexp),
	  m_ignNewlines(0),
	  m_eof(false), m_file(false), m_termState(0) {
	lexStreamDepthAdd(1);
    }
    ~VPreStream() {
	lexStreamDepthAdd(-1);
    }
private:
    void lexStreamDepthAdd(int delta);
};

//======================================================================
// Class entry for each per-lexer state

class VPreLex {
  public:	// Used only by VPreLex.cpp and VPreProc.cpp
    VPreProcImp*	m_preimpp;	// Preprocessor lexor belongs to
    stack<VPreStream*>	m_streampStack;	// Stack of processing files
    int			m_streamDepth;	// Depth of stream processing
   
    void debugErr()
    {
    //  cout<<m_preimpp->m_lineChars()<<endl;
    }
   
    int getBufSize(); // return the current size of unread string 
    char* getInputBuffer();
    char* getInputBuffer1();
    void initBuffer(const string & buf);
  
  
    YY_BUFFER_STATE 	m_bufferState;	// Flex state
    VFileLine*		m_tokFilelinep;	// Starting position of current token

    // State to lexer
    static VPreLex* s_currentLexp;	///< Current lexing point
    int		m_keepComments;		///< Emit comments in output text
    int		m_keepWhitespace;	///< Emit all whitespace in output text
    bool	m_pedantic;	///< Obey standard; don't Substitute `error
    bool	m_synthesis;	///< Remove translate_offs

    // State from lexer
    int		m_formalLevel;	///< Parenthesis counting inside def formals
    int		m_parenLevel;	///< Parenthesis counting inside def args
    bool	m_defCmtSlash;	///< /*...*/ comment in define had \ ending
    string	m_defValue;	///< Definition value being built.
    int		m_enterExit;	///< For VL_LINE, the enter/exit level

    // CONSTRUCTORS
    VPreLex(VPreProcImp* preimpp, VFileLine* filelinep) {
	m_preimpp = preimpp;
	m_streamDepth = 0;
	m_keepComments = 0;
	m_keepWhitespace = 1;
	m_pedantic = false;
	m_synthesis = false;
	m_formalLevel = 0;
	m_parenLevel = 0;
	m_defCmtSlash = false;
	m_tokFilelinep = filelinep;
	m_enterExit = 0;
	initFirstBuffer(filelinep);
    }
    ~VPreLex() {
	while (!m_streampStack.empty()) { delete m_streampStack.top(); m_streampStack.pop(); }
	yy_delete_buffer(m_bufferState); m_bufferState=NULL;
    }

    /// Called by VPreLex.l from lexer
    VPreStream* curStreamp() { return m_streampStack.top(); }  // Can't be empty, "EOF" is on top
    VFileLine* curFilelinep() { return curStreamp()->m_curFilelinep; }
    void curFilelinep(VFileLine* fl) { curStreamp()->m_curFilelinep = fl; }
    void appendDefValue(const char* textp, size_t len) 
    { 
      m_defValue.append(textp,len); 
    }
    void lineDirective(const char* textp) { curFilelinep(curFilelinep()->lineDirective(textp, m_enterExit/*ref*/)); }
    void linenoInc() { if (curStreamp()->m_ignNewlines) curStreamp()->m_ignNewlines--;
	else curFilelinep(curFilelinep()->create(curFilelinep()->lineno()+1)); }
    /// Called by VPreProc.cpp to inform lexer
    void pushStateDefArg(int level);
    void pushStateDefForm();
    void pushStateDefValue();
    void pushStateIncFilename();
    void scanNewFile(VFileLine* filelinep);
    void scanBytes(const string& str);
    void scanBytesBack(const string& str);
    size_t inputToLex(char* buf, size_t max_size);
    /// Called by VPreProc.cpp to get data from lexer
    YY_BUFFER_STATE currentBuffer();
    int  lex();
    int	 currentStartState();
    void dumpSummary();
    void dumpStack();
    void unused();
    // Called by VPreStream
    void streamDepthAdd(int delta) { m_streamDepth += delta; }
    int streamDepth() const { return m_streamDepth; }
    /// Utility
    static int debug();
    static void debug(int level);
    static string cleanDbgStrg(const string& in);
     string currentUnreadChars();
  
    
private:
    string endOfStream(bool& againr);
    void initFirstBuffer(VFileLine* filelinep);
    void scanSwitchStream(VPreStream* streamp);
};

inline void VPreStream::lexStreamDepthAdd(int delta) { m_lexp->streamDepthAdd(delta); }

#endif // Guard

src/VPreProc.cpp

0 → 100644
+1910 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading