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