diff options
Diffstat (limited to 'jam-files/engine/headers.c')
-rw-r--r-- | jam-files/engine/headers.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/jam-files/engine/headers.c b/jam-files/engine/headers.c new file mode 100644 index 00000000..b9d8f637 --- /dev/null +++ b/jam-files/engine/headers.c @@ -0,0 +1,203 @@ +/* + * Copyright 1993, 2000 Christopher Seiwald. + * + * This file is part of Jam - see jam.c for Copyright information. + */ +/* This file is ALSO: + * Copyright 2001-2004 David Abrahams. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + */ + +# include "jam.h" +# include "lists.h" +# include "parse.h" +# include "compile.h" +# include "rules.h" +# include "variable.h" +# include "regexp.h" +# include "headers.h" +# include "hdrmacro.h" +# include "newstr.h" + +#ifdef OPT_HEADER_CACHE_EXT +# include "hcache.h" +#endif + +/* + * headers.c - handle #includes in source files + * + * Using regular expressions provided as the variable $(HDRSCAN), + * headers() searches a file for #include files and phonies up a + * rule invocation: + * + * $(HDRRULE) <target> : <include files> ; + * + * External routines: + * headers() - scan a target for include files and call HDRRULE + * + * Internal routines: + * headers1() - using regexp, scan a file and build include LIST + * + * 04/13/94 (seiwald) - added shorthand L0 for null list pointer + * 09/10/00 (seiwald) - replaced call to compile_rule with evaluate_rule, + * so that headers() doesn't have to mock up a parse structure + * just to invoke a rule. + */ + +#ifndef OPT_HEADER_CACHE_EXT +static LIST *headers1( LIST *l, char *file, int rec, regexp *re[]); +#endif + +/* + * headers() - scan a target for include files and call HDRRULE + */ + +# define MAXINC 10 + +void +headers( TARGET *t ) +{ + LIST * hdrscan; + LIST * hdrrule; + #ifndef OPT_HEADER_CACHE_EXT + LIST * headlist = 0; + #endif + regexp * re[ MAXINC ]; + int rec = 0; + + if ( !( hdrscan = var_get( "HDRSCAN" ) ) || + !( hdrrule = var_get( "HDRRULE" ) ) ) + return; + + if ( DEBUG_HEADER ) + printf( "header scan %s\n", t->name ); + + /* Compile all regular expressions in HDRSCAN */ + while ( ( rec < MAXINC ) && hdrscan ) + { + re[ rec++ ] = regex_compile( hdrscan->string ); + hdrscan = list_next( hdrscan ); + } + + /* Doctor up call to HDRRULE rule */ + /* Call headers1() to get LIST of included files. */ + { + FRAME frame[1]; + frame_init( frame ); + lol_add( frame->args, list_new( L0, t->name ) ); +#ifdef OPT_HEADER_CACHE_EXT + lol_add( frame->args, hcache( t, rec, re, hdrscan ) ); +#else + lol_add( frame->args, headers1( headlist, t->boundname, rec, re ) ); +#endif + + if ( lol_get( frame->args, 1 ) ) + { + /* The third argument to HDRRULE is the bound name of + * $(<) */ + lol_add( frame->args, list_new( L0, t->boundname ) ); + + list_free( evaluate_rule( hdrrule->string, frame ) ); + } + + /* Clean up. */ + frame_free( frame ); + } +} + + +/* + * headers1() - using regexp, scan a file and build include LIST. + */ + +#ifdef OPT_HEADER_CACHE_EXT +LIST * +#else +static LIST * +#endif +headers1( + LIST * l, + char * file, + int rec, + regexp * re[] ) +{ + FILE * f; + char buf[ 1024 ]; + int i; + static regexp * re_macros = 0; + +#ifdef OPT_IMPROVED_PATIENCE_EXT + static int count = 0; + ++count; + if ( ((count == 100) || !( count % 1000 )) && DEBUG_MAKE ) + printf("...patience...\n"); +#endif + + /* the following regexp is used to detect cases where a */ + /* file is included through a line line "#include MACRO" */ + if ( re_macros == 0 ) + re_macros = regex_compile( + "^[ ]*#[ ]*include[ ]*([A-Za-z][A-Za-z0-9_]*).*$" ); + + if ( !( f = fopen( file, "r" ) ) ) + return l; + + while ( fgets( buf, sizeof( buf ), f ) ) + { + int size = strlen( buf ); + /* Remove trailing \r and \n, if any. */ + while ( ( size > 0 ) && + ( buf[ size - 1 ] == '\n' ) && + ( buf[ size - 1 ] == '\r' ) ) + { + buf[ size - 1 ] = '\0'; + --size; + } + + for ( i = 0; i < rec; ++i ) + if ( regexec( re[i], buf ) && re[i]->startp[1] ) + { + re[i]->endp[1][0] = '\0'; + + if ( DEBUG_HEADER ) + printf( "header found: %s\n", re[i]->startp[1] ); + + l = list_new( l, newstr( re[i]->startp[1] ) ); + } + + /* special treatment for #include MACRO */ + if ( regexec( re_macros, buf ) && re_macros->startp[1] ) + { + char* header_filename; + + re_macros->endp[1][0] = '\0'; + + if ( DEBUG_HEADER ) + printf( "macro header found: %s", re_macros->startp[1] ); + + header_filename = macro_header_get( re_macros->startp[1] ); + if ( header_filename ) + { + if ( DEBUG_HEADER ) + printf( " resolved to '%s'\n", header_filename ); + l = list_new( l, newstr( header_filename ) ); + } + else + { + if ( DEBUG_HEADER ) + printf( " ignored !!\n" ); + } + } + } + + fclose( f ); + + return l; +} + + +void regerror( char * s ) +{ + printf( "re error %s\n", s ); +} |