1 | /* |
---|
2 | * Copyright 1993, 2000 Christopher Seiwald. |
---|
3 | * |
---|
4 | * This file is part of Jam - see jam.c for Copyright information. |
---|
5 | */ |
---|
6 | |
---|
7 | /* This file is ALSO: |
---|
8 | * Copyright 2001-2004 David Abrahams. |
---|
9 | * Distributed under the Boost Software License, Version 1.0. |
---|
10 | * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) |
---|
11 | */ |
---|
12 | |
---|
13 | # include "jam.h" |
---|
14 | # include "lists.h" |
---|
15 | # include "parse.h" |
---|
16 | # include "compile.h" |
---|
17 | # include "rules.h" |
---|
18 | # include "variable.h" |
---|
19 | # include "regexp.h" |
---|
20 | # include "hdrmacro.h" |
---|
21 | # include "hash.h" |
---|
22 | # include "newstr.h" |
---|
23 | # include "strings.h" |
---|
24 | |
---|
25 | /* |
---|
26 | * hdrmacro.c - handle header files that define macros used in |
---|
27 | * #include statements. |
---|
28 | * |
---|
29 | * we look for lines like "#define MACRO <....>" or '#define MACRO " "' |
---|
30 | * in the target file. When found, we |
---|
31 | * |
---|
32 | * we then phony up a rule invocation like: |
---|
33 | * |
---|
34 | * $(HDRRULE) <target> : <resolved included files> ; |
---|
35 | * |
---|
36 | * External routines: |
---|
37 | * headers1() - scan a target for "#include MACRO" lines and try |
---|
38 | * to resolve them when needed |
---|
39 | * |
---|
40 | * Internal routines: |
---|
41 | * headers1() - using regexp, scan a file and build include LIST |
---|
42 | * |
---|
43 | * 04/13/94 (seiwald) - added shorthand L0 for null list pointer |
---|
44 | * 09/10/00 (seiwald) - replaced call to compile_rule with evaluate_rule, |
---|
45 | * so that headers() doesn't have to mock up a parse structure |
---|
46 | * just to invoke a rule. |
---|
47 | */ |
---|
48 | |
---|
49 | static LIST *header_macros1( LIST *l, char *file, int rec, regexp *re[] ); |
---|
50 | |
---|
51 | /* this type is used to store a dictionary of file header macros */ |
---|
52 | typedef struct header_macro |
---|
53 | { |
---|
54 | char* symbol; |
---|
55 | char* filename; /* we could maybe use a LIST here ?? */ |
---|
56 | |
---|
57 | } HEADER_MACRO; |
---|
58 | |
---|
59 | static struct hash* header_macros_hash = 0; |
---|
60 | |
---|
61 | /* |
---|
62 | * headers() - scan a target for include files and call HDRRULE |
---|
63 | */ |
---|
64 | |
---|
65 | # define MAXINC 10 |
---|
66 | |
---|
67 | void |
---|
68 | macro_headers( TARGET *t ) |
---|
69 | { |
---|
70 | static regexp *re = 0; |
---|
71 | FILE *f; |
---|
72 | char buf[ 1024 ]; |
---|
73 | |
---|
74 | if ( DEBUG_HEADER ) |
---|
75 | printf( "macro header scan for %s\n", t->name ); |
---|
76 | |
---|
77 | /* this regexp is used to detect lines of the form */ |
---|
78 | /* "#define MACRO <....>" or "#define MACRO "....." */ |
---|
79 | /* in the header macro files.. */ |
---|
80 | if ( re == 0 ) |
---|
81 | { |
---|
82 | re = regex_compile( |
---|
83 | "^[ ]*#[ ]*define[ ]*([A-Za-z][A-Za-z0-9_]*)[ ]*" |
---|
84 | "[<\"]([^\">]*)[\">].*$" ); |
---|
85 | } |
---|
86 | |
---|
87 | if( !( f = fopen( t->boundname, "r" ) ) ) |
---|
88 | return; |
---|
89 | |
---|
90 | while( fgets( buf, sizeof( buf ), f ) ) |
---|
91 | { |
---|
92 | HEADER_MACRO var, *v = &var; |
---|
93 | |
---|
94 | if ( regexec( re, buf ) && re->startp[1] ) |
---|
95 | { |
---|
96 | /* we detected a line that looks like "#define MACRO filename */ |
---|
97 | re->endp[1][0] = '\0'; |
---|
98 | re->endp[2][0] = '\0'; |
---|
99 | |
---|
100 | if ( DEBUG_HEADER ) |
---|
101 | printf( "macro '%s' used to define filename '%s' in '%s'\n", |
---|
102 | re->startp[1], re->startp[2], t->boundname ); |
---|
103 | |
---|
104 | /* add macro definition to hash table */ |
---|
105 | if ( !header_macros_hash ) |
---|
106 | header_macros_hash = hashinit( sizeof( HEADER_MACRO ), "hdrmacros" ); |
---|
107 | |
---|
108 | v->symbol = re->startp[1]; |
---|
109 | v->filename = 0; |
---|
110 | if ( hashenter( header_macros_hash, (HASHDATA **)&v ) ) |
---|
111 | { |
---|
112 | v->symbol = newstr( re->startp[1] ); /* never freed */ |
---|
113 | v->filename = newstr( re->startp[2] ); /* never freed */ |
---|
114 | } |
---|
115 | /* XXXX: FOR NOW, WE IGNORE MULTIPLE MACRO DEFINITIONS !! */ |
---|
116 | /* WE MIGHT AS WELL USE A LIST TO STORE THEM.. */ |
---|
117 | } |
---|
118 | } |
---|
119 | |
---|
120 | fclose( f ); |
---|
121 | } |
---|
122 | |
---|
123 | |
---|
124 | char* |
---|
125 | macro_header_get( const char* macro_name ) |
---|
126 | { |
---|
127 | HEADER_MACRO var, *v = &var; |
---|
128 | |
---|
129 | v->symbol = (char*)macro_name; |
---|
130 | |
---|
131 | if( header_macros_hash && hashcheck( header_macros_hash, (HASHDATA **)&v ) ) |
---|
132 | { |
---|
133 | if ( DEBUG_HEADER ) |
---|
134 | printf( "### macro '%s' evaluated to '%s'\n", macro_name, v->filename ); |
---|
135 | return v->filename; |
---|
136 | } |
---|
137 | return 0; |
---|
138 | } |
---|
139 | |
---|