• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /*
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"
39 #include "jam_strings.h"
40 #include "subst.h"
41 #include "variable.h"
42 #include "output.h"
43 
44 #include <errno.h>
45 #include <string.h>
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 
macro_headers(TARGET * t)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" ) ) )
86     {
87         err_printf( "[errno %d] failed to scan include file '%s': %s",
88             errno, object_str( t->boundname ), strerror(errno) );
89         return;
90     }
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 
macro_header_get(OBJECT * macro_name)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 }
147