Add include path and line directives.

This commit is contained in:
steve 1999-07-03 20:03:47 +00:00
parent 3d1f0b3da2
commit 413e0d2aa6
5 changed files with 267 additions and 34 deletions

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.1 1999/07/03 17:24:11 steve Exp $"
#ident "$Id: Makefile.in,v 1.2 1999/07/03 20:03:47 steve Exp $"
#
#
SHELL = /bin/sh
@ -68,5 +68,6 @@ installdirs: mkinstalldirs
uninstall:
rm -f $(bindir)/ivlpp
lexor.o: lexor.c parse.h
lexor.o: lexor.c parse.h globals.h
main.o: main.c globals.h
parse.o: parse.c

47
ivlpp/globals.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef __globals_H
#define __globals_H
/*
* Copyright (c) 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
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: globals.h,v 1.1 1999/07/03 20:03:47 steve Exp $"
#endif
# include <stdio.h>
extern void reset_lexor(FILE*out, const char*ipath);
extern void define_macro(const char*name, const char*value);
/* These variables contain the include directories to be searched when
an include directive in encountered. */
extern char**include_dir;
extern unsigned include_cnt;
/* This flag is true if #line directives are to be generated. */
extern int line_direct_flag;
/* This is the entry to the parser. */
extern int yyparse();
/*
* $Log: globals.h,v $
* Revision 1.1 1999/07/03 20:03:47 steve
* Add include path and line directives.
*
*/
#endif

View File

@ -24,9 +24,55 @@ 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.
USAGE:
ivlpp <file>
ivlpp [options] <file>
The <file> parameter is the name of the file to be read and
preprocessed. The resulting output is sent to standard output.
preprocessed. The resulting output is sent to standard output. The
valid options include:
-Dname[=value]
Predefine the symbol ``name'' to have the specified
value. If the value is not specified, then ``1'' is
used. This is mostly of use for controlling conditional
compilaiton.
This option does *not* override existing `define
directives in the source file.
-I <dir>
Add a directory to the include path. Normally, only "." is
in the search path. The -I flag causes other directories
to be searched for a named file. There may be as many -I
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.
-o <file>
Send the output to the named file, instead of to standard
output.
-v
Print version and copyright information
LOCATING INCLUDED FILES
The ivlpp preprocessor implements the `include directives by
substituting the contents of the included file in place of the line
with the `include directive. The name that the programmer specifies is
a file name. Normally, the preprocessor looks in the current working
directory for the named file. However, the ``-I'' flags can be used to
specify a path of directories to search for named include files. The
current directory will be searched first, followed by all the include
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.

View File

@ -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.1 1999/07/03 17:24:11 steve Exp $"
#ident "$Id: lexor.lex,v 1.2 1999/07/03 20:03:47 steve Exp $"
#endif
# include <stdio.h>
@ -28,6 +28,10 @@
# include <assert.h>
# include "parse.h"
# include "globals.h"
static void output_init();
#define YY_USER_INIT output_init()
static void def_match();
static void def_start();
@ -38,6 +42,18 @@ static void do_include();
static int yywrap();
struct include_stack_t {
char* path;
FILE*file;
unsigned lineno;
YY_BUFFER_STATE yybs;
struct include_stack_t*next;
};
static struct include_stack_t*istack = 0;
static struct include_stack_t*standby = 0;
%}
%x PPINCLUDE
@ -55,7 +71,7 @@ static int yywrap();
<PPINCLUDE>[ \t\b\f\r] { ; }
<PPINCLUDE>\n { BEGIN(0); do_include(); }
<PPINCLUDE>\n { istack->lineno += 1; BEGIN(0); do_include(); }
/* Detect the define directive, and match the name. Match any
@ -67,7 +83,7 @@ static int yywrap();
<PPDEFINE>.* { do_define(); }
<PPDEFINE>\n { BEGIN(0); ECHO; }
<PPDEFINE>\n { istack->lineno += 1; BEGIN(0); ECHO; }
/* This pattern notices macros and arranges for it to be replaced. */
`[a-zA-Z][a-zA-Z0-9]* { def_match(); }
@ -76,7 +92,7 @@ static int yywrap();
output. Very easy. */
. { ECHO; }
\n { ECHO; }
\n { istack->lineno += 1; ECHO; }
%%
/* Defined macros are kept in this table for convenient lookup. As
@ -122,11 +138,11 @@ static void def_start()
sscanf(yytext, "`define %s", def_name);
}
static void do_define()
void define_macro(const char*name, const char*value)
{
struct define_t*def = malloc(sizeof(struct define_t));
def->name = strdup(def_name);
def->value = strdup(yytext);
def->name = strdup(name);
def->value = strdup(value);
def->left = 0;
def->right = 0;
if (def_table == 0) {
@ -164,6 +180,11 @@ static void do_define()
}
}
static void do_define()
{
define_macro(def_name, yytext);
}
/*
* Include file handling works by keeping an include stack of the
* files that are opened and being processed. The first item on the
@ -180,17 +201,11 @@ static void do_define()
* parsing.
*/
struct include_stack_t {
char* path;
FILE*file;
unsigned lineno;
YY_BUFFER_STATE yybs;
struct include_stack_t*next;
};
static struct include_stack_t*istack = 0;
static struct include_stack_t*standby = 0;
static void output_init()
{
if (line_direct_flag)
fprintf(yyout, "#line \"%s\" 0\n", istack->path);
}
static void include_filename()
{
@ -198,11 +213,28 @@ static void include_filename()
standby = malloc(sizeof(struct include_stack_t));
standby->path = strdup(yytext+1);
standby->path[strlen(standby->path)-1] = 0;
standby->lineno = 0;
}
static void do_include()
{
standby->file = fopen(standby->path, "r");
if (standby->path[0] == '/') {
standby->file = fopen(standby->path, "r");
} else {
unsigned idx = 0;
standby->file = 0;
for (idx = 0 ; idx < include_cnt ; idx += 1) {
char path[4096];
sprintf(path, "%s/%s", include_dir[idx], standby->path);
standby->file = fopen(path, "r");
if (standby->file)
break;
}
}
if (standby->file == 0) {
perror(standby->path);
exit(1);
@ -214,6 +246,9 @@ static void do_include()
istack = standby;
standby = 0;
yy_switch_to_buffer(yy_new_buffer(istack->file, YY_BUF_SIZE));
if (line_direct_flag)
fprintf(yyout, "#line \"%s\" %u\n", istack->path, istack->lineno);
}
static int yywrap()
@ -230,6 +265,9 @@ static int yywrap()
return 1;
yy_switch_to_buffer(istack->yybs);
if (line_direct_flag)
fprintf(yyout, "#line \"%s\" %u\n", istack->path, istack->lineno);
return 0;
}
@ -238,7 +276,7 @@ static int yywrap()
* opened, and the lexor is initialized. The include stack is cleared
* and ready to go.
*/
void reset_lexor(const char*path)
void reset_lexor(FILE*out, const char*path)
{
struct include_stack_t*isp = malloc(sizeof(struct include_stack_t));
isp->path = strdup(path);
@ -248,6 +286,8 @@ void reset_lexor(const char*path)
exit(1);
}
yyout = out;
yyrestart(isp->file);
assert(istack == 0);

View File

@ -1,6 +1,6 @@
const char COPYRIGHT[] =
"Copyright (c) 1999 Stephen Williams (steve@icarus.com)";
/*
* Copyright (c) 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
* General Public License as published by the Free Software
@ -17,28 +17,127 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: main.c,v 1.1 1999/07/03 17:24:11 steve Exp $"
#ident "$Id: main.c,v 1.2 1999/07/03 20:03:47 steve Exp $"
#endif
# include <stdio.h>
const char NOTICE[] =
" This program is free software; you can redistribute it and/or modify\n"
" it under the terms of the GNU General Public License as published by\n"
" the Free Software Foundation; either version 2 of the License, or\n"
" (at your option) any later version.\n"
"\n"
" This program is distributed in the hope that it will be useful,\n"
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
" GNU General Public License for more details.\n"
"\n"
" You should have received a copy of the GNU General Public License\n"
" along with this program; if not, write to the Free Software\n"
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
;
extern void reset_lexor(const char*);
extern int yylex();
const char VERSION[] = "$Name: $ $State: Exp $";
# include <stdio.h>
# include <malloc.h>
# include <unistd.h>
# include <string.h>
# include "globals.h"
char**include_dir = 0;
unsigned include_cnt = 0;
int line_direct_flag = 0;
int main(int argc, char*argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: %s <file>\n", argv[0]);
return 1;
int opt;
unsigned flag_errors = 0;
char*out_path = 0;
FILE*out;
include_dir = malloc(sizeof(char*));
include_dir[0] = strdup(".");
include_cnt = 1;
while ((opt = getopt(argc, argv, "D:I:Lo:v")) != EOF) switch (opt) {
case 'D': {
char*tmp = strdup(optarg);
char*val = strchr(tmp, '=');
if (val)
*val++ = 0;
else
val = "1";
define_macro(tmp, val);
free(tmp);
break;
}
case 'I':
include_dir = realloc(include_dir, (include_cnt+1)*sizeof(char*));
include_dir[include_cnt] = strdup(optarg);
include_cnt += 1;
break;
case 'L':
line_direct_flag = 1;
break;
case 'o':
if (out_path) {
fprintf(stderr, "duplicate -o flag.\n");
} else {
out_path = optarg;
}
break;
case 'v':
fprintf(stderr, "Icarus Verilog Preprocessor version %s\n",
VERSION);
fprintf(stderr, "%s\n", COPYRIGHT);
fputs(NOTICE, stderr);
break;
default:
flag_errors += 1;
break;
}
reset_lexor(argv[1]);
if (optind == argc)
flag_errors += 1;
if (flag_errors) {
fprintf(stderr, "\nUsage: %s [-v][-L][-I<dir>][-D<def>] <file>\n"
" -D<def> - Predefine a value.\n"
" -I<dir> - Add an include file search directory\n"
" -L - Emit line number directives\n"
" -o<fil> - Send the output to <fil>\n"
" -v - Print version information\n",
argv[0]);
return flag_errors;
}
if (out_path) {
out = fopen(out_path, "w");
if (out == 0) {
perror(out_path);
exit(1);
}
} else {
out = stdout;
}
reset_lexor(out, argv[optind]);
return yyparse();
}
/*
* $Log: main.c,v $
* Revision 1.2 1999/07/03 20:03:47 steve
* Add include path and line directives.
*
* Revision 1.1 1999/07/03 17:24:11 steve
* Add a preprocessor.
*