| /* |
| * 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 ); |
| } |