summaryrefslogtreecommitdiff
path: root/jam-files/engine/hdrmacro.c
blob: 43031d48ffd2bc320177d2828a6d08f5bf712274 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * Copyright 1993, 2000 Christopher Seiwald.
 *
 * This file is part of Jam - see jam.c for Copyright information.
 */

/*  This file is ALSO:
 *  Copyright 2001-2004 David Abrahams.
 *  Distributed under the Boost Software License, Version 1.0.
 *  (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 */

# include "jam.h"
# include "lists.h"
# include "parse.h"
# include "compile.h"
# include "rules.h"
# include "variable.h"
# include "regexp.h"
# include "hdrmacro.h"
# include "hash.h"
# include "newstr.h"
# include "strings.h"

/*
 * hdrmacro.c - handle header files that define macros used in
 *              #include statements.
 *
 *  we look for lines like "#define MACRO  <....>" or '#define MACRO  "    "'
 *  in the target file. When found, we
 *
 *  we then phony up a rule invocation like:
 *
 *  $(HDRRULE) <target> : <resolved included files> ;
 *
 * External routines:
 *    headers1() - scan a target for "#include MACRO" lines and try
 *                 to resolve them when needed
 *
 * Internal routines:
 *    headers1() - using regexp, scan a file and build include LIST
 *
 * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
 * 09/10/00 (seiwald) - replaced call to compile_rule with evaluate_rule,
 *      so that headers() doesn't have to mock up a parse structure
 *      just to invoke a rule.
 */

/* this type is used to store a dictionary of file header macros */
typedef struct header_macro
{
  char * symbol;
  char * filename;  /* we could maybe use a LIST here ?? */
} HEADER_MACRO;

static struct hash * header_macros_hash = 0;


/*
 * headers() - scan a target for include files and call HDRRULE
 */

# define MAXINC 10

void
macro_headers( TARGET *t )
{
    static regexp *re = 0;
    FILE    *f;
    char    buf[ 1024 ];

    if ( DEBUG_HEADER )
        printf( "macro header scan for %s\n", t->name );

    /* this regexp is used to detect lines of the form       */
    /* "#define  MACRO  <....>" or "#define  MACRO  "....."  */
    /* in the header macro files..                           */
    if ( re == 0 )
    {
        re = regex_compile(
            "^[     ]*#[    ]*define[   ]*([A-Za-z][A-Za-z0-9_]*)[  ]*"
            "[<\"]([^\">]*)[\">].*$" );
    }

    if ( !( f = fopen( t->boundname, "r" ) ) )
        return;

    while ( fgets( buf, sizeof( buf ), f ) )
    {
        HEADER_MACRO var;
        HEADER_MACRO *v = &var;

        if ( regexec( re, buf ) && re->startp[1] )
        {
            /* we detected a line that looks like "#define  MACRO  filename */
            re->endp[1][0] = '\0';
            re->endp[2][0] = '\0';

            if ( DEBUG_HEADER )
                printf( "macro '%s' used to define filename '%s' in '%s'\n",
                        re->startp[1], re->startp[2], t->boundname );

            /* add macro definition to hash table */
            if ( !header_macros_hash )
                header_macros_hash = hashinit( sizeof( HEADER_MACRO ), "hdrmacros" );

            v->symbol   = re->startp[1];
            v->filename = 0;
            if ( hashenter( header_macros_hash, (HASHDATA **)&v ) )
            {
                v->symbol   = newstr( re->startp[1] );  /* never freed */
                v->filename = newstr( re->startp[2] );  /* never freed */
            }
            /* XXXX: FOR NOW, WE IGNORE MULTIPLE MACRO DEFINITIONS !! */
            /*       WE MIGHT AS WELL USE A LIST TO STORE THEM..      */
        }
    }

    fclose( f );
}


char * macro_header_get( const char * macro_name )
{
    HEADER_MACRO var;
    HEADER_MACRO * v = &var;

    v->symbol = (char* )macro_name;

    if ( header_macros_hash && hashcheck( header_macros_hash, (HASHDATA **)&v ) )
    {
        if ( DEBUG_HEADER )
            printf( "### macro '%s' evaluated to '%s'\n", macro_name, v->filename );
        return v->filename;
    }
    return 0;
}