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 */
31
32# include "jam.h"
33# include "lists.h"
34# include "parse.h"
35# include "compile.h"
36# include "rules.h"
37# include "variable.h"
38# include "regexp.h"
39# include "headers.h"
40# include "newstr.h"
41
42#ifdef OPT_HEADER_CACHE_EXT
43# include "hcache.h"
44#endif
45
46#ifndef OPT_HEADER_CACHE_EXT
47static LIST *headers1( const char *file, LIST *hdrscan );
48#endif
49
50/*
51 * headers() - scan a target for include files and call HDRRULE
52 */
53
54# define MAXINC 10
55
56void
57headers( TARGET *t )
58{
59	LIST	*hdrscan;
60	LIST	*hdrrule;
61	LIST	*hdrcache;
62	LOL	lol;
63
64	if( !( hdrscan = var_get( "HDRSCAN" ) ) ||
65	    !( hdrrule = var_get( "HDRRULE" ) ) )
66	        return;
67
68	/* Doctor up call to HDRRULE rule */
69	/* Call headers1() to get LIST of included files. */
70
71	if( DEBUG_HEADER )
72	    printf( "header scan %s\n", t->name );
73
74	lol_init( &lol );
75
76	lol_add( &lol, list_new( L0, t->name, 1 ) );
77#ifdef OPT_HEADER_CACHE_EXT
78	lol_add( &lol, hcache( t, hdrscan ) );
79#else
80	lol_add( &lol, headers1( t->boundname, hdrscan ) );
81#endif
82
83	if( lol_get( &lol, 1 ) )
84	{
85	    int jmp = JMP_NONE;
86	    list_free( evaluate_rule( hdrrule->string, &lol, L0, &jmp ) );
87	}
88
89	/* Clean up */
90
91	lol_free( &lol );
92}
93
94/*
95 * headers1() - using regexp, scan a file and build include LIST
96 */
97
98#ifdef OPT_HEADER_CACHE_EXT
99LIST *
100#else
101static LIST *
102#endif
103headers1(
104	const char *file,
105	LIST *hdrscan )
106{
107	FILE	*f;
108	int	i;
109	int	rec = 0;
110	LIST	*result = 0;
111	regexp	*re[ MAXINC ];
112	char	buf[ 1024 ];
113
114	if( !( f = fopen( file, "r" ) ) )
115	    return result;
116
117	while( rec < MAXINC && hdrscan )
118	{
119	    re[rec++] = regcomp( hdrscan->string );
120	    hdrscan = list_next( hdrscan );
121	}
122
123	while( fgets( buf, sizeof( buf ), f ) )
124	{
125	    for( i = 0; i < rec; i++ )
126		if( regexec( re[i], buf ) && re[i]->startp[1] )
127	    {
128		/* Copy and terminate extracted string. */
129
130		char buf2[ MAXSYM ];
131		int l = re[i]->endp[1] - re[i]->startp[1];
132		if (l > MAXSYM) {
133			printf("MAXSYM is too low! Need at least %d\n", l);
134			exit(-1);
135		}
136		memcpy( buf2, re[i]->startp[1], l );
137		buf2[ l ] = 0;
138		result = list_new( result, buf2, 0 );
139
140		if( DEBUG_HEADER )
141		    printf( "header found: %s\n", buf2 );
142	    }
143	}
144
145	while( rec )
146	    free( (char *)re[--rec] );
147
148	fclose( f );
149
150	return result;
151}
152