diff --git a/ivlpp/Makefile.in b/ivlpp/Makefile.in index db5656119..40472e1a6 100644 --- a/ivlpp/Makefile.in +++ b/ivlpp/Makefile.in @@ -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 diff --git a/ivlpp/globals.h b/ivlpp/globals.h new file mode 100644 index 000000000..bb4b644e9 --- /dev/null +++ b/ivlpp/globals.h @@ -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 + +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 diff --git a/ivlpp/ivlpp.txt b/ivlpp/ivlpp.txt index 5a9f07219..40ea82b1a 100644 --- a/ivlpp/ivlpp.txt +++ b/ivlpp/ivlpp.txt @@ -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 + ivlpp [options] The 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 + 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 + 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. diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index a08ded103..a1bbeee89 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -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 @@ -28,6 +28,10 @@ # include # 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(); [ \t\b\f\r] { ; } -\n { BEGIN(0); do_include(); } +\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(); .* { do_define(); } -\n { BEGIN(0); ECHO; } +\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); diff --git a/ivlpp/main.c b/ivlpp/main.c index 49756d764..83941856e 100644 --- a/ivlpp/main.c +++ b/ivlpp/main.c @@ -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 +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 +# include +# include +# include +# 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 \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][-D] \n" + " -D - Predefine a value.\n" + " -I - Add an include file search directory\n" + " -L - Emit line number directives\n" + " -o - Send the output to \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. *