blob: b9d8f6370d787e5f1752be95091a3e2fc0c22f0d [file] [log] [blame]
/*
* 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 );
}