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().
45 #ifndef OPT_HEADER_CACHE_EXT
46 static LIST *headers1 (const char *file, LIST *hdrscan);
52 * headers() - scan a target for include files and call HDRRULE
56 void headers (TARGET
*t
) {
61 if (!(hdrscan
= var_get("HDRSCAN")) || !(hdrrule
= var_get("HDRRULE"))) return;
62 /* doctor up call to HDRRULE rule */
63 /* call headers1() to get LIST of included files */
64 if (DEBUG_HEADER
) printf("header scan %s\n", t
->name
);
66 lol_add(&lol
, list_new(L0
, t
->name
, 1));
68 #ifdef OPT_HEADER_CACHE_EXT
69 lol_add(&lol, hcache(t, hdrscan));
71 lol_add(&lol, headers1(t->boundname, hdrscan));
74 lol_add(&lol
, hcache(t
, hdrscan
));
75 if (lol_get(&lol
, 1)) list_free(evaluate_rule(hdrrule
->string
, &lol
, L0
));
82 * headers1() - using regexp, scan a file and build include LIST
85 #ifndef OPT_HEADER_CACHE_EXT
89 LIST
*headers1 (const char *file
, LIST
*hdrscan
) {
97 char buf
[4096], buf2
[MAXSYM
];
99 if (!(f
= fopen(file
, "r"))) return result
;
100 while (rec
< MAXINC
&& hdrscan
) {
101 //printf("header re %d: [%s]\n", rec, hdrscan->string);
102 err
= hsrxCompile(&re
[rec
++], hdrscan
->string
, HSRX_EXTENDED
|HSRX_NEWLINE
);
104 hsrxError(err
, &re
[rec
-1], buf
, sizeof(buf
));
105 printf("FATAL: %s\n", buf
);
108 hdrscan
= list_next(hdrscan
);
110 /* the following regexp is used to detect cases where a */
111 /* file is included through a line line "#include MACRO" */
112 err
= hsrxCompile(&re_macros
, "^[[:space:]]*#[[:space:]]*include[[:space:]]*([A-Za-z][A-Za-z0-9_]*).*$", HSRX_EXTENDED
|HSRX_NEWLINE
);
114 hsrxError(err
, &re_macros
, buf
, sizeof(buf
));
115 printf("FATAL: %s\n", buf
);
118 if (DEBUG_HEADER
) printf("header processing: [%s] (%d)\n", file
, rec
);
119 while (fgets(buf
, sizeof(buf
), f
)) {
120 for (i
= 0; i
< rec
; ++i
) {
121 if (hsrxExec(&re
[i
], buf
, 2, mt
, 0) == HSRX_NOERROR
/* && mt[1].rm_eo > mt[1].rm_so*/) {
122 /* copy and terminate extracted string */
123 int l
= mt
[1].rm_eo
-mt
[1].rm_so
;
125 memcpy(buf2
, buf
+mt
[1].rm_so
, l
); buf2
[l
] = 0;
126 result
= list_new(result
, buf2
, 0);
127 if (DEBUG_HEADER
) printf("header found: %s\n", buf2
);
130 /* special treatment for #include MACRO */
131 if (hsrxExec(&re_macros
, buf
, 2, mt
, 0) == HSRX_NOERROR
&& mt
[1].rm_eo
> mt
[1].rm_so
) {
132 const char *header_filename
;
133 int l
= mt
[1].rm_eo
-mt
[1].rm_so
;
135 memcpy(buf2
, buf
+mt
[1].rm_so
, l
); buf2
[l
] = 0;
136 if (DEBUG_HEADER
) printf("macro header found: %s", buf2
);
137 header_filename
= macro_header_get(buf2
);
138 if (header_filename
) {
139 if (DEBUG_HEADER
) printf(" resolved to '%s'\n", header_filename
);
140 result
= list_new(result
, header_filename
, 0);
142 if (DEBUG_HEADER
) printf(" ignored !!\n");
146 hsrxFree(&re_macros
);
147 while (rec
) hsrxFree(&re
[--rec
]);