diff --git a/ivlpp/globals.h b/ivlpp/globals.h index 12c94cc3f..400459a66 100644 --- a/ivlpp/globals.h +++ b/ivlpp/globals.h @@ -1,7 +1,7 @@ #ifndef __globals_H #define __globals_H /* - * Copyright (c) 1999 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2007 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 @@ -18,15 +18,14 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: globals.h,v 1.7 2002/08/12 01:35:02 steve Exp $" -#endif # include extern void reset_lexor(FILE*out, char*paths[]); +extern void load_precompiled_defines(FILE*src); extern void define_macro(const char*name, const char*value, int keyword, int argc); +extern void dump_precompiled_defines(FILE*out); /* These variables contain the include directories to be searched when an include directive in encountered. */ @@ -43,28 +42,4 @@ extern FILE *depend_file; /* This is the entry to the parser. */ extern int yyparse(); -/* - * $Log: globals.h,v $ - * Revision 1.7 2002/08/12 01:35:02 steve - * conditional ident string using autoconfig. - * - * Revision 1.6 2002/04/04 05:26:13 steve - * Add dependency generation. - * - * Revision 1.5 2000/09/13 22:33:13 steve - * undefined macros are null (with warnings.) - * - * Revision 1.4 2000/08/20 17:49:04 steve - * Clean up warnings and portability issues. - * - * Revision 1.3 2000/06/30 15:49:44 steve - * Handle errors from parser slightly differently. - * - * Revision 1.2 1999/09/05 22:33:18 steve - * Take multiple source files on the command line. - * - * Revision 1.1 1999/07/03 20:03:47 steve - * Add include path and line directives. - * - */ #endif diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 9ea99d1e2..496067097 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -1,7 +1,7 @@ %{ /* - * Copyright (c) 1999-2002 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2007 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 @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: lexor.lex,v 1.48 2007/05/30 23:21:20 steve Exp $" -#endif # include "config.h" @@ -1331,6 +1328,90 @@ static int yywrap() return 0; } +/* + * The dump_precompiled_defines() and load_precompiled_defines() + * functions dump/load macro definitions to/from a file. The defines + * are in the form: + * + * ::: + * + * for easy extraction. The value is already precompiled to handle + * macro substitution. The is the number of bytes in the + * . This is necessary because the value may contain arbitrary + * text, including ':' and \n characters. + * + * Each record is terminated by a \n character. + */ +static void do_dump_precompiled_defines(FILE*out, struct define_t*table) +{ + if (!table->keyword) + fprintf(out, "%s:%d:%zd:%s\n", table->name, table->argc, + strlen(table->value), table->value); + if (table->left) + do_dump_precompiled_defines(out, table->left); + if (table->right) + do_dump_precompiled_defines(out, table->right); +} + +void dump_precompiled_defines(FILE*out) +{ + if (def_table) + do_dump_precompiled_defines(out, def_table); +} + +void load_precompiled_defines(FILE*src) +{ + char buf[4096]; + int ch; + + while ( (ch = fgetc(src)) != EOF ) { + char *cp = buf; + + char*name = 0; + char*value = 0; + int argc = 0; + size_t len = 0; + + name = cp; + while ( ch != EOF && ch != ':') { + *cp++ = ch; + ch = fgetc(src); + } + if (ch != ':') return; + + /* Terminate the name string. */ + *cp++ = 0; + /* Read the argc number */ + ch = fgetc(src); + while (isdigit(ch)) { + argc = 10*argc + ch-'0'; + ch = fgetc(src); + } + if (ch != ':') return; + + ch = fgetc(src); + while (isdigit(ch)) { + len = 10*len + ch-'0'; + ch = fgetc(src); + } + if (ch != ':') return; + + value = cp; + while (len > 0) { + ch = fgetc(src); + if (ch == EOF) return; + *cp++ = ch; + len -= 1; + } + *cp++ = 0; + + ch = fgetc(src); + if (ch != '\n') return; + + define_macro(name, value, 0, argc); + } +} + /* * This function initializes the whole process. The first file is * opened, and the lexor is initialized. The include stack is cleared diff --git a/ivlpp/main.c b/ivlpp/main.c index d50f9c704..6cab9f6c2 100644 --- a/ivlpp/main.c +++ b/ivlpp/main.c @@ -1,5 +1,5 @@ const char COPYRIGHT[] = - "Copyright (c) 1999 Stephen Williams (steve@icarus.com)"; + "Copyright (c) 1999-2007 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 @@ -16,9 +16,6 @@ const char COPYRIGHT[] = * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: main.c,v 1.23 2006/10/02 18:16:18 steve Exp $" -#endif # include "config.h" @@ -61,6 +58,7 @@ extern const char*optarg; /* Path to the dependency file, if there is one. */ char *dep_path = NULL; + /* * Keep in source_list an array of pointers to file names. The array * is terminated by a pointer to null. @@ -200,6 +198,8 @@ int main(int argc, char*argv[]) unsigned flag_errors = 0; char*out_path = 0; FILE*out; + char*precomp_out_path = 0; + FILE*precomp_out = NULL; /* Define preprocessor keywords that I plan to just pass. */ define_macro("celldefine", "`celldefine", 1, 0); @@ -225,7 +225,7 @@ int main(int argc, char*argv[]) include_dir[0] = 0; /* 0 is reserved for the current files path. */ include_dir[1] = strdup("."); - while ((opt=getopt(argc, argv, "F:f:K:Lo:v")) != EOF) switch (opt) { + while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:v")) != EOF) switch (opt) { case 'F': flist_read_flags(optarg); @@ -260,6 +260,25 @@ int main(int argc, char*argv[]) } break; + case 'p': + if (precomp_out_path) { + fprintf(stderr, "duplicate -p flag.\n"); + } else { + precomp_out_path = optarg; + } + break; + + case 'P': { + FILE*src = fopen(optarg, "rb"); + if (src == 0) { + perror(optarg); + exit(1); + } + load_precompiled_defines(src); + fclose(src); + break; + } + case 'v': fprintf(stderr, "Icarus Verilog Preprocessor version %s\n", VERSION); @@ -279,6 +298,8 @@ int main(int argc, char*argv[]) " -K - Define a keyword macro that I just pass\n" " -L - Emit line number directives\n" " -o - Send the output to \n" + " -p - Write precompiled defines to \n" + " -P - Read precompiled defines from \n" " -v - Print version information\n", argv[0]); return flag_errors; @@ -309,6 +330,14 @@ int main(int argc, char*argv[]) out = stdout; } + if (precomp_out_path) { + precomp_out = fopen(precomp_out_path, "wb"); + if (precomp_out == 0) { + perror(precomp_out_path); + exit(1); + } + } + if(dep_path) { depend_file = fopen(dep_path, "w"); if (depend_file == 0) { @@ -331,5 +360,10 @@ int main(int argc, char*argv[]) fclose(depend_file); } + if (precomp_out) { + dump_precompiled_defines(precomp_out); + fclose(precomp_out); + } + return error_count; }