Supoprt precompiled defines

Core preprocessor support for writing out and reading precompiled
defines. The preprocessor can read initial precompiled defines from
any number of specified source files, and can write all the defines
into a specified output file.
This commit is contained in:
Stephen Williams 2007-12-30 18:47:32 -08:00
parent ef1739dbec
commit a3c1fb8c8a
3 changed files with 127 additions and 37 deletions

View File

@ -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 <stdio.h>
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

View File

@ -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:
*
* <name>:<argc>:<len>:<value>
*
* for easy extraction. The value is already precompiled to handle
* macro substitution. The <len> is the number of bytes in the
* <value>. 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

View File

@ -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<def> - Define a keyword macro that I just pass\n"
" -L - Emit line number directives\n"
" -o<fil> - Send the output to <fil>\n"
" -p<fil> - Write precompiled defines to <fil>\n"
" -P<fil> - Read precompiled defines from <fil>\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;
}