Add a preprocessor.

This commit is contained in:
steve 1999-07-03 17:24:11 +00:00
parent 3ff6912bdd
commit 3d1f0b3da2
6 changed files with 450 additions and 0 deletions

6
ivlpp/.cvsignore Normal file
View File

@ -0,0 +1,6 @@
lexor.c
parse.c
parse.h
parse.output
Makefile
ivlpp

72
ivlpp/Makefile.in Normal file
View File

@ -0,0 +1,72 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version. In order to redistribute the software in
# binary form, you will need a Picture Elements Binary Software
# License.
#
# 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 Library General Public License for more details.
#
# You should have received a copy of the GNU Library 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
#
#ident "$Id: Makefile.in,v 1.1 1999/07/03 17:24:11 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.0
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @CPPFLAGS@ @DEFS@
CFLAGS = @CFLAGS@
LDFLAGS = @LDFLAGS@
all: ivlpp
O = main.o lexor.o parse.o
ivlpp: $O
$(CC) $(LDFLAGS) $O -o ivlpp
lexor.c: lexor.lex
flex -s -olexor.c lexor.lex
parse.h parse.c: parse.y
bison --verbose -t -d parse.y -o parse.c
install: all installdirs $(bindir)/ivl
$(bindir)/ivlpp: ivlpp
$(INSTALL_PROGRAM) ./ivlpp $(bindir)/ivlpp
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(includedir) $(bindir)
uninstall:
rm -f $(bindir)/ivlpp
lexor.o: lexor.c parse.h
parse.o: parse.c

32
ivlpp/ivlpp.txt Normal file
View File

@ -0,0 +1,32 @@
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
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.
USAGE:
ivlpp <file>
The <file> parameter is the name of the file to be read and
preprocessed. The resulting output is sent to standard output.

256
ivlpp/lexor.lex Normal file
View File

@ -0,0 +1,256 @@
%{
/*
* 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: lexor.lex,v 1.1 1999/07/03 17:24:11 steve Exp $"
#endif
# include <stdio.h>
# include <malloc.h>
# include <string.h>
# include <assert.h>
# include "parse.h"
static void def_match();
static void def_start();
static void do_define();
static void include_filename();
static void do_include();
static int yywrap();
%}
%x PPINCLUDE
%x PPDEFINE
%%
/* This set of patterns matches the include directive and the name
that follows it. when the directive ends, the do_include function
performs the include operation. */
^`include { BEGIN(PPINCLUDE); }
<PPINCLUDE>\"[^\"]*\" { include_filename(); }
<PPINCLUDE>[ \t\b\f\r] { ; }
<PPINCLUDE>\n { BEGIN(0); do_include(); }
/* Detect the define directive, and match the name. Match any
white space that might be found, as well. After I get the
directive and the name, go into PPDEFINE mode and prepare to
collect the defined value. */
^`define[ \t]+[a-zA-Z][a-zA-Z0-9]*[ \t]+ { BEGIN(PPDEFINE); def_start(); }
<PPDEFINE>.* { do_define(); }
<PPDEFINE>\n { BEGIN(0); ECHO; }
/* This pattern notices macros and arranges for it to be replaced. */
`[a-zA-Z][a-zA-Z0-9]* { def_match(); }
/* Any text that is not a directive just gets passed through to the
output. Very easy. */
. { ECHO; }
\n { ECHO; }
%%
/* Defined macros are kept in this table for convenient lookup. As
`define directives are matched (and the do_define() function
called) the tree is built up to match names with values. If a
define redefines an existing name, the new value it taken. */
struct define_t {
char*name;
char*value;
struct define_t*left, *right;
};
static struct define_t*def_table = 0;
/* When a macro use is discovered in the source, this function is
used to look up the name and emit the substitution in its
place. If the name is not found, then the `name string is written
out instead. */
static void def_match()
{
struct define_t*cur = def_table;
while (cur) {
int cmp = strcmp(yytext+1, cur->name);
if (cmp == 0) break;
if (cmp < 0)
cur = cur->left;
else
cur = cur->right;
}
if (cur)
fprintf(yyout, "%s", cur->value);
else
fprintf(yyout, "%s", yytext);
}
static char def_name[256];
static void def_start()
{
sscanf(yytext, "`define %s", def_name);
}
static void do_define()
{
struct define_t*def = malloc(sizeof(struct define_t));
def->name = strdup(def_name);
def->value = strdup(yytext);
def->left = 0;
def->right = 0;
if (def_table == 0) {
def_table = def;
} else {
struct define_t*cur = def_table;
for (;;) {
int cmp = strcmp(def->name, cur->name);
if (cmp == 0) {
free(cur->value);
cur->value = def->value;
free(def->name);
free(def);
break;
} else if (cmp < 0) {
if (cur->left == 0) {
cur->left = def;
break;
} else {
cur = cur->left;
}
} else {
if (cur->right == 0) {
cur->right = def;
break;
} else {
cur = cur->right;
}
}
}
}
}
/*
* Include file handling works by keeping an include stack of the
* files that are opened and being processed. The first item on the
* stack is the current file being scanned. If I get to an include
* statement,
* open the new file,
* save the current buffer context,
* create a new buffer context,
* and push the new file information.
*
* When the file runs out, the yywrap closes the file and deletes the
* buffer. If after popping the current file information there is
* another file on the stack, restore its buffer context and resume
* 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 include_filename()
{
assert(standby == 0);
standby = malloc(sizeof(struct include_stack_t));
standby->path = strdup(yytext+1);
standby->path[strlen(standby->path)-1] = 0;
}
static void do_include()
{
standby->file = fopen(standby->path, "r");
if (standby->file == 0) {
perror(standby->path);
exit(1);
}
assert(standby->file);
standby->next = istack;
istack->yybs = YY_CURRENT_BUFFER;
istack = standby;
standby = 0;
yy_switch_to_buffer(yy_new_buffer(istack->file, YY_BUF_SIZE));
}
static int yywrap()
{
struct include_stack_t*isp = istack;
istack = isp->next;
yy_delete_buffer(YY_CURRENT_BUFFER);
fclose(isp->file);
free(isp->path);
free(isp);
if (istack == 0)
return 1;
yy_switch_to_buffer(istack->yybs);
return 0;
}
/*
* This function initializes the whole process. The first file is
* opened, and the lexor is initialized. The include stack is cleared
* and ready to go.
*/
void reset_lexor(const char*path)
{
struct include_stack_t*isp = malloc(sizeof(struct include_stack_t));
isp->path = strdup(path);
isp->file = fopen(path, "r");
if (isp->file == 0) {
perror(path);
exit(1);
}
yyrestart(isp->file);
assert(istack == 0);
istack = isp;
isp->next = 0;
}

46
ivlpp/main.c Normal file
View File

@ -0,0 +1,46 @@
/*
* 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: main.c,v 1.1 1999/07/03 17:24:11 steve Exp $"
#endif
# include <stdio.h>
extern void reset_lexor(const char*);
extern int yylex();
int main(int argc, char*argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: %s <file>\n", argv[0]);
return 1;
}
reset_lexor(argv[1]);
return yyparse();
}
/*
* $Log: main.c,v $
* Revision 1.1 1999/07/03 17:24:11 steve
* Add a preprocessor.
*
*/

38
ivlpp/parse.y Normal file
View File

@ -0,0 +1,38 @@
%{
/*
* 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: parse.y,v 1.1 1999/07/03 17:24:11 steve Exp $"
#endif
static void yyerror(const char*msg);
%}
%%
file : ;
%%
void yyerror(const char*msg)
{
fprintf(stderr, "ivlpp error: %s\n", msg);
}