1 /*
2  * Copyright 1993, 2000 Christopher Seiwald.
3  *
4  * This file is part of Jam - see jam.c for Copyright information.
5  */
6 
7 /*
8  * headers.c - handle #includes in source files
9  *
10  * Using regular expressions provided as the variable $(HDRSCAN),
11  * headers() searches a file for #include files and phonies up a
12  * rule invocation:
13  *
14  *	$(HDRRULE) <target> : <include files> ;
15  *
16  * External routines:
17  *    headers() - scan a target for include files and call HDRRULE
18  *
19  * Internal routines:
20  *    headers1() - using regexp, scan a file and build include LIST
21  *
22  * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
23  * 09/10/00 (seiwald) - replaced call to compile_rule with evaluate_rule,
24  *		so that headers() doesn't have to mock up a parse structure
25  *		just to invoke a rule.
26  * 03/02/02 (seiwald) - rules can be invoked via variable names
27  * 10/22/02 (seiwald) - list_new() now does its own newstr()/copystr()
28  * 11/04/02 (seiwald) - const-ing for string literals
29  * 12/09/02 (seiwald) - push regexp creation down to headers1().
30  * 01/05/07 (seiwald) - evaluate_rule takes PARSE for debugging.
31  */
32 
33 # include "jam.h"
34 # include "lists.h"
35 # include "parse.h"
36 # include "compile.h"
37 # include "rules.h"
38 # include "variable.h"
39 # include "regexp.h"
40 # include "headers.h"
41 # include "newstr.h"
42 
43 static LIST *headers1( const char *file, LIST *hdrscan );
44 
45 /*
46  * headers() - scan a target for include files and call HDRRULE
47  */
48 
49 # define MAXINC 10
50 
51 void
headers(TARGET * t)52 headers( TARGET *t )
53 {
54 	LIST	*hdrscan;
55 	LIST	*hdrrule;
56 	LIST	*hdrcache;
57 	LOL	lol;
58 
59 	if( !( hdrscan = var_get( "HDRSCAN" ) ) ||
60 	    !( hdrrule = var_get( "HDRRULE" ) ) )
61 	        return;
62 
63 	/* Doctor up call to HDRRULE rule */
64 	/* Call headers1() to get LIST of included files. */
65 
66 	if( DEBUG_HEADER )
67 	    printf( "header scan %s\n", t->name );
68 
69 	lol_init( &lol );
70 
71 	lol_add( &lol, list_new( L0, t->name, 1 ) );
72 	lol_add( &lol, headers1( t->boundname, hdrscan ) );
73 
74 	if( lol_get( &lol, 1 ) )
75 	    list_free( evaluate_rule( 0, hdrrule->string, &lol, L0 ) );
76 
77 	/* Clean up */
78 
79 	lol_free( &lol );
80 }
81 
82 /*
83  * headers1() - using regexp, scan a file and build include LIST
84  */
85 
86 static LIST *
headers1(const char * file,LIST * hdrscan)87 headers1(
88 	const char *file,
89 	LIST *hdrscan )
90 {
91 	FILE	*f;
92 	int	i;
93 	int	rec = 0;
94 	LIST	*result = 0;
95 	regexp	*re[ MAXINC ];
96 	char	buf[ 1024 ];
97 
98 	if( !( f = fopen( file, "r" ) ) )
99 	    return result;
100 
101 	while( rec < MAXINC && hdrscan )
102 	{
103 	    re[rec++] = regcomp( hdrscan->string );
104 	    hdrscan = list_next( hdrscan );
105 	}
106 
107 	while( fgets( buf, sizeof( buf ), f ) )
108 	{
109 	    for( i = 0; i < rec; i++ )
110 		if( regexec( re[i], buf ) && re[i]->startp[1] )
111 	    {
112 		/* Copy and terminate extracted string. */
113 
114 		char buf2[ MAXSYM ];
115 		int l = re[i]->endp[1] - re[i]->startp[1];
116 		memcpy( buf2, re[i]->startp[1], l );
117 		buf2[ l ] = 0;
118 		result = list_new( result, buf2, 0 );
119 
120 		if( DEBUG_HEADER )
121 		    printf( "header found: %s\n", buf2 );
122 	    }
123 	}
124 
125 	while( rec )
126 	    free( (char *)re[--rec] );
127 
128 	fclose( f );
129 
130 	return result;
131 }
132