Support line directives from the preprocessor.

This commit is contained in:
steve 1999-07-03 21:27:22 +00:00
parent 954b42b66b
commit 4939e9fe61
2 changed files with 63 additions and 79 deletions

View File

@ -22,7 +22,7 @@ THE IVL PREPROCESSOR
The ivlpp command is a verilog preprocessor that handles file
inclusion and macro substitution. The program runs separate from the
actual compiler so as to ease the task of the compiler proper, and
provide a means of preprocessing files off-line.
provides a means of preprocessing files off-line.
USAGE:
@ -49,10 +49,10 @@ valid options include:
flags as needed.
-L
Add to the output #line directives. The ivl compiler
understands these directives and uses them to keep track
of the current line of the original source file. This
makes error messages more meaningful.
Generate #line directives. The ivl compiler understands
these directives and uses them to keep track of the
current line of the original source file. This makes error
messages more meaningful.
-o <file>
Send the output to the named file, instead of to standard
@ -76,3 +76,30 @@ directories in the order that the -I flag appears.
The exception to this process is include files that have a name that
starts with the '/' character. These file names are ``rooted names''
and must be in the rooted location specified.
GENERATED LINE DIRECTIVES
Compilers generally try to print along with their error messages the
file and line number where the error occurred. Icarus Verilog is no
exception. However, if a separate preprocessor is actually selecting
and opening files, then the line numbers counted by the compiler
proper will not reflect the actual line numbers in the source file.
To handle this situation, the preprocessor can generate line
directives. These directives are lines of the form:
#line <name> <num>
where <name> is the file name in double-quotes and <num> is the line
number in the file. The parser changes the filename and line number
counters in such a way that the next line is line number <num>+1 in
the file named <name>. For example:
#line "foo.vl" 5
// I am on line 6 in file foo.vl.
The preprocessor generates a #line directive every time it switches
files. That includes starting an included file (#line "foo.vlh" 0) or
returning to the including file.

105
lexor.lex
View File

@ -1,7 +1,7 @@
%{
/*
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: lexor.lex,v 1.27 1999/06/22 03:59:37 steve Exp $"
#ident "$Id: lexor.lex,v 1.28 1999/07/03 21:27:22 steve Exp $"
#endif
//# define YYSTYPE lexval
@ -38,9 +38,9 @@ extern string vl_file;
extern YYLTYPE yylloc;
static void reset_lexor();
static void line_directive();
static int check_identifier(const char*name);
static void ppinclude_filename();
static void ppdo_include();
static verinum*make_sized_binary(const char*txt);
static verinum*make_sized_dec(const char*txt);
static verinum*make_unsized_dec(const char*txt);
@ -58,11 +58,12 @@ static int comment_enter;
%x LCOMMENT
%x CSTRING
%s UDPTABLE
%x PPINCLUDE
%x PPTIMESCALE
%%
^"#line"[ ]+\"[^\"]*\"[ ]+[0-9]+.* { line_directive(); }
[ \t\b\f\r] { ; }
\n { yylloc.first_line += 1; }
@ -210,19 +211,6 @@ static int comment_enter;
yylloc.first_line += 1;
BEGIN(0); }
`include {
BEGIN(PPINCLUDE); }
<PPINCLUDE>\"[^\"]*\" {
ppinclude_filename(); }
<PPINCLUDE>[ \t\b\f\r] { ; }
<PPINCLUDE>\n {
BEGIN(0);
yylloc.first_line += 1;
ppdo_include(); }
. { cerr << yylloc.first_line << ": unmatched character (";
if (isgraph(yytext[0]))
@ -769,71 +757,40 @@ static verinum*make_unsized_dec(const char*txt)
return make_dec_with_size(INTEGER_WIDTH, false, txt+1);
}
struct include_stack_t {
string path;
FILE*file;
unsigned lineno;
YY_BUFFER_STATE yybs;
struct include_stack_t*next;
};
static include_stack_t*include_stack = 0;
static string ppinclude_path;
static void ppinclude_filename()
{
ppinclude_path = yytext+1;
ppinclude_path = ppinclude_path.substr(0, ppinclude_path.length()-1);
}
static void ppdo_include()
{
FILE*file = fopen(ppinclude_path.c_str(), "r");
if (file == 0) {
cerr << ppinclude_path << ": Unable to open include file." << endl;
return;
}
include_stack_t*isp = new include_stack_t;
isp->path = vl_file;
isp->file = vl_input;
isp->lineno = yylloc.first_line;
isp->next = include_stack;
isp->yybs = YY_CURRENT_BUFFER;
vl_file = ppinclude_path;
vl_input = file;
yylloc.first_line = 1;
yylloc.text = vl_file.c_str();
yy_switch_to_buffer(yy_new_buffer(vl_input, YY_BUF_SIZE));
include_stack = isp;
}
static int yywrap()
{
include_stack_t*isp = include_stack;
if (isp == 0)
return 1;
return 1;
}
yy_delete_buffer(YY_CURRENT_BUFFER);
fclose(vl_input);
/*
* The line directive matches lines of the form #line "foo" N and
* calls this function. Here I parse out the file name and line
* number, and change the yylloc to suite.
*/
static void line_directive()
{
char*qt1 = strchr(yytext, '"');
assert(qt1);
qt1 += 1;
vl_input = isp->file;
vl_file = isp->path;
yy_switch_to_buffer(isp->yybs);
yylloc.first_line = isp->lineno;
yylloc.text = vl_file.c_str();
include_stack = isp->next;
delete isp;
return 0;
char*qt2 = strchr(qt1, '"');
assert(qt2);
char*buf = new char[qt2-qt1+1];
strncpy(buf, qt1, qt2-qt1);
buf[qt2-qt1] = 0;
delete[]yylloc.text;
yylloc.text = buf;
qt2 += 1;
yylloc.first_line = strtoul(qt2,0,0);
}
static void reset_lexor()
{
yyrestart(vl_input);
include_stack = 0;
yylloc.first_line = 1;
yylloc.text = vl_file.c_str();
yylloc.text = strdup(vl_file.c_str());
}