2 * Copyright 1993, 2000 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
8 * headers.c - handle #includes in source files
10 * Using regular expressions provided as the variable $(HDRSCAN),
11 * headers() searches a file for #include files and phonies up a
14 * $(HDRRULE) <target> : <include files> ;
17 * headers() - scan a target for include files and call HDRRULE
20 * headers1() - using regexp, scan a file and build include LIST
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().
46 #ifndef OPT_HEADER_CACHE_EXT
47 static LIST *headers1 (const char *file, LIST *hdrscan);
53 * headers() - scan a target for include files and call HDRRULE
57 void headers (TARGET
*t
) {
62 if (!(hdrscan
= var_get("HDRSCAN")) || !(hdrrule
= var_get("HDRRULE"))) return;
63 /* doctor up call to HDRRULE rule */
64 /* call headers1() to get LIST of included files */
65 if (DEBUG_HEADER
) printf("header scan %s\n", t
->name
);
67 lol_add(&lol
, list_new(L0
, t
->name
, 1));
69 #ifdef OPT_HEADER_CACHE_EXT
70 lol_add(&lol, hcache(t, hdrscan));
72 lol_add(&lol, headers1(t->boundname, hdrscan));
75 lol_add(&lol
, hcache(t
, hdrscan
));
76 if (lol_get(&lol
, 1)) list_free(evaluate_rule(hdrrule
->string
, &lol
, L0
));
83 * headers1() - using regexp, scan a file and build include LIST
86 #ifndef OPT_HEADER_CACHE_EXT
90 LIST
*headers1 (const char *file
, LIST
*hdrscan
) {
95 re9_prog_t
*re
[MAXINC
];
96 re9_prog_prepared_t
*repp
[MAXINC
];
97 re9_prog_t
*re_macros
;
98 re9_prog_prepared_t
*repp_macros
;
101 int line_size
= 16384;
102 char *buf
; /* line_size size */
104 if (DEBUG_HEADER
) printf("DBG: trying header [%s]\n", file
);
105 if (!(f
= fopen(file
, "r"))) return result
;
106 while (rec
< MAXINC
&& hdrscan
) {
107 //printf("header re %d: [%s]\n", rec, hdrscan->string);
108 if ((re
[rec
] = re9_compile(hdrscan
->string
, RE9_FLAG_NONUTF8
, &errmsg
)) == NULL
) {
109 printf("FATAL: %s\n", errmsg
);
112 if ((repp
[rec
] = re9_prepare(re
[rec
])) == NULL
) {
113 printf("FATAL: out of memory\n");
117 hdrscan
= list_next(hdrscan
);
119 /* the following regexp is used to detect cases where a */
120 /* file is included through a line line "#include MACRO" */
121 re_macros
= re9_compile("^\\s*#\\s*include\\s+([A-Za-z_][A-Za-z0-9_]*).*$", RE9_FLAG_NONUTF8
, &errmsg
);
122 if (re_macros
== NULL
) {
123 printf("FATAL: %s\n", errmsg
);
126 if ((repp_macros
= re9_prepare(re_macros
)) == NULL
) {
127 printf("FATAL: out of memory\n");
130 if (DEBUG_HEADER
) printf("header processing: [%s] (%d)\n", file
, rec
);
131 if ((buf
= malloc(line_size
)) == NULL
) { fprintf(stderr
, "FATAL: out of memory!\n"); abort(); }
133 while (fgets(buf
, line_size
, f
)) {
134 for (i
= 0; i
< rec
; ++i
) {
135 mt
[0].sp
= mt
[0].ep
= NULL
;
136 if (re9_prepared_execute(repp
[i
], RE9_FLAG_NONUTF8
, buf
, mt
, 2) > 0 && mt
[1].sp
!= NULL
) {
137 /* copy and terminate extracted string */
138 int l
= mt
[1].ep
-mt
[1].sp
;
139 dstr_set_buf(&buf2
, mt
[1].sp
, l
);
140 result
= list_new(result
, dstr_cstr(&buf2
), 0);
141 if (DEBUG_HEADER
) printf("header found: %s\n", dstr_cstr(&buf2
));
144 /* special treatment for #include MACRO */
145 mt
[0].sp
= mt
[0].ep
= NULL
;
146 if (re9_prepared_execute(repp_macros
, RE9_FLAG_NONUTF8
, buf
, mt
, 2) > 0 && mt
[1].sp
!= NULL
) {
147 const char *header_filename
;
148 int l
= mt
[1].ep
-mt
[1].sp
;
149 dstr_set_buf(&buf2
, mt
[1].sp
, l
);
150 if (DEBUG_HEADER
) printf("macro header found: %s", dstr_cstr(&buf2
));
151 header_filename
= macro_header_get(dstr_cstr(&buf2
));
152 if (header_filename
) {
153 if (DEBUG_HEADER
) printf(" resolved to '%s'\n", header_filename
);
154 result
= list_new(result
, header_filename
, 0);
156 if (DEBUG_HEADER
) printf(" ignored !!\n");
163 re9_prepared_free(repp_macros
);
166 re9_prepared_free(repp
[rec
]);