]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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. | |
1e59de90 | 10 | * (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt) |
7c673cae FG |
11 | */ |
12 | ||
13 | /* | |
14 | * hdrmacro.c - handle header files that define macros used in #include | |
15 | * statements. | |
16 | * | |
17 | * we look for lines like "#define MACRO <....>" or '#define MACRO " "' in | |
18 | * the target file. When found, we then phony up a rule invocation like: | |
19 | * | |
20 | * $(HDRRULE) <target> : <resolved included files> ; | |
21 | * | |
22 | * External routines: | |
23 | * headers1() - scan a target for "#include MACRO" lines and try to resolve | |
24 | * them when needed | |
25 | * | |
26 | * Internal routines: | |
27 | * headers1() - using regexp, scan a file and build include LIST | |
28 | */ | |
29 | ||
30 | #include "jam.h" | |
31 | #include "hdrmacro.h" | |
32 | ||
33 | #include "compile.h" | |
34 | #include "hash.h" | |
35 | #include "lists.h" | |
36 | #include "object.h" | |
37 | #include "parse.h" | |
38 | #include "rules.h" | |
f67539c2 | 39 | #include "jam_strings.h" |
7c673cae FG |
40 | #include "subst.h" |
41 | #include "variable.h" | |
42 | #include "output.h" | |
43 | ||
20effc67 TL |
44 | #include <errno.h> |
45 | #include <string.h> | |
7c673cae FG |
46 | |
47 | /* this type is used to store a dictionary of file header macros */ | |
48 | typedef struct header_macro | |
49 | { | |
50 | OBJECT * symbol; | |
51 | OBJECT * filename; /* we could maybe use a LIST here ?? */ | |
52 | } HEADER_MACRO; | |
53 | ||
54 | static struct hash * header_macros_hash = 0; | |
55 | ||
56 | ||
57 | /* | |
58 | * headers() - scan a target for include files and call HDRRULE | |
59 | */ | |
60 | ||
61 | #define MAXINC 10 | |
62 | ||
63 | void macro_headers( TARGET * t ) | |
64 | { | |
65 | static regexp * re = 0; | |
66 | FILE * f; | |
67 | char buf[ 1024 ]; | |
68 | ||
69 | if ( DEBUG_HEADER ) | |
70 | out_printf( "macro header scan for %s\n", object_str( t->name ) ); | |
71 | ||
72 | /* This regexp is used to detect lines of the form | |
73 | * "#define MACRO <....>" or "#define MACRO "....." | |
74 | * in the header macro files. | |
75 | */ | |
76 | if ( !re ) | |
77 | { | |
78 | OBJECT * const re_str = object_new( | |
79 | "^[ ]*#[ ]*define[ ]*([A-Za-z][A-Za-z0-9_]*)[ ]*" | |
80 | "[<\"]([^\">]*)[\">].*$" ); | |
81 | re = regex_compile( re_str ); | |
82 | object_free( re_str ); | |
83 | } | |
84 | ||
85 | if ( !( f = fopen( object_str( t->boundname ), "r" ) ) ) | |
20effc67 TL |
86 | { |
87 | err_printf( "[errno %d] failed to scan include file '%s': %s", | |
88 | errno, object_str( t->boundname ), strerror(errno) ); | |
7c673cae | 89 | return; |
20effc67 | 90 | } |
7c673cae FG |
91 | |
92 | while ( fgets( buf, sizeof( buf ), f ) ) | |
93 | { | |
94 | HEADER_MACRO var; | |
95 | HEADER_MACRO * v = &var; | |
96 | ||
97 | if ( regexec( re, buf ) && re->startp[ 1 ] ) | |
98 | { | |
99 | OBJECT * symbol; | |
100 | int found; | |
101 | /* we detected a line that looks like "#define MACRO filename */ | |
102 | ( (char *)re->endp[ 1 ] )[ 0 ] = '\0'; | |
103 | ( (char *)re->endp[ 2 ] )[ 0 ] = '\0'; | |
104 | ||
105 | if ( DEBUG_HEADER ) | |
106 | out_printf( "macro '%s' used to define filename '%s' in '%s'\n", | |
107 | re->startp[ 1 ], re->startp[ 2 ], object_str( t->boundname ) | |
108 | ); | |
109 | ||
110 | /* add macro definition to hash table */ | |
111 | if ( !header_macros_hash ) | |
112 | header_macros_hash = hashinit( sizeof( HEADER_MACRO ), | |
113 | "hdrmacros" ); | |
114 | ||
115 | symbol = object_new( re->startp[ 1 ] ); | |
116 | v = (HEADER_MACRO *)hash_insert( header_macros_hash, symbol, &found | |
117 | ); | |
118 | if ( !found ) | |
119 | { | |
120 | v->symbol = symbol; | |
121 | v->filename = object_new( re->startp[ 2 ] ); /* never freed */ | |
122 | } | |
123 | else | |
124 | object_free( symbol ); | |
125 | /* XXXX: FOR NOW, WE IGNORE MULTIPLE MACRO DEFINITIONS !! */ | |
126 | /* WE MIGHT AS WELL USE A LIST TO STORE THEM.. */ | |
127 | } | |
128 | } | |
129 | ||
130 | fclose( f ); | |
131 | } | |
132 | ||
133 | ||
134 | OBJECT * macro_header_get( OBJECT * macro_name ) | |
135 | { | |
136 | HEADER_MACRO * v; | |
137 | if ( header_macros_hash && ( v = (HEADER_MACRO *)hash_find( | |
138 | header_macros_hash, macro_name ) ) ) | |
139 | { | |
140 | if ( DEBUG_HEADER ) | |
141 | out_printf( "### macro '%s' evaluated to '%s'\n", object_str( macro_name | |
142 | ), object_str( v->filename ) ); | |
143 | return v->filename; | |
144 | } | |
145 | return 0; | |
146 | } |