From 3d1f0b3da2490eb8131d58efc2fb1c5ced3e8c2d Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 3 Jul 1999 17:24:11 +0000 Subject: [PATCH] Add a preprocessor. --- ivlpp/.cvsignore | 6 ++ ivlpp/Makefile.in | 72 +++++++++++++ ivlpp/ivlpp.txt | 32 ++++++ ivlpp/lexor.lex | 256 ++++++++++++++++++++++++++++++++++++++++++++++ ivlpp/main.c | 46 +++++++++ ivlpp/parse.y | 38 +++++++ 6 files changed, 450 insertions(+) create mode 100644 ivlpp/.cvsignore create mode 100644 ivlpp/Makefile.in create mode 100644 ivlpp/ivlpp.txt create mode 100644 ivlpp/lexor.lex create mode 100644 ivlpp/main.c create mode 100644 ivlpp/parse.y diff --git a/ivlpp/.cvsignore b/ivlpp/.cvsignore new file mode 100644 index 000000000..4e7295523 --- /dev/null +++ b/ivlpp/.cvsignore @@ -0,0 +1,6 @@ +lexor.c +parse.c +parse.h +parse.output +Makefile +ivlpp diff --git a/ivlpp/Makefile.in b/ivlpp/Makefile.in new file mode 100644 index 000000000..db5656119 --- /dev/null +++ b/ivlpp/Makefile.in @@ -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 diff --git a/ivlpp/ivlpp.txt b/ivlpp/ivlpp.txt new file mode 100644 index 000000000..5a9f07219 --- /dev/null +++ b/ivlpp/ivlpp.txt @@ -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 + +The parameter is the name of the file to be read and +preprocessed. The resulting output is sent to standard output. diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex new file mode 100644 index 000000000..a08ded103 --- /dev/null +++ b/ivlpp/lexor.lex @@ -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 +# include +# include +# include + +# 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); } + +\"[^\"]*\" { include_filename(); } + +[ \t\b\f\r] { ; } + +\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(); } + +.* { do_define(); } + +\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; +} diff --git a/ivlpp/main.c b/ivlpp/main.c new file mode 100644 index 000000000..49756d764 --- /dev/null +++ b/ivlpp/main.c @@ -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 + +extern void reset_lexor(const char*); +extern int yylex(); + +int main(int argc, char*argv[]) +{ + if (argc != 2) { + fprintf(stderr, "Usage: %s \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. + * + */ + diff --git a/ivlpp/parse.y b/ivlpp/parse.y new file mode 100644 index 000000000..dbf71d0d4 --- /dev/null +++ b/ivlpp/parse.y @@ -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); +}