bumped version to 2.5.8
[k8jam.git] / headers.c
blob18c7503a227254e35e80058f8bf0cb86291ad38a
1 /*
2 * Copyright 1993, 2000 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
7 /*
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
12 * rule invocation:
14 * $(HDRRULE) <target> : <include files> ;
16 * External routines:
17 * headers() - scan a target for include files and call HDRRULE
19 * Internal routines:
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().
32 # include "jam.h"
33 # include "lists.h"
34 # include "parse.h"
35 # include "compile.h"
36 # include "rules.h"
37 # include "variable.h"
38 # include "regexp.h"
39 # include "headers.h"
40 # include "newstr.h"
41 # include "hdrmacro.h"
44 static LIST *headers1 (const char *file, LIST *hdrscan);
48 * headers() - scan a target for include files and call HDRRULE
50 # define MAXINC 10
52 void headers (TARGET *t) {
53 LIST *hdrscan;
54 LIST *hdrrule;
55 LOL lol;
57 if (!(hdrscan = var_get("HDRSCAN")) || !(hdrrule = var_get("HDRRULE"))) return;
58 /* Doctor up call to HDRRULE rule */
59 /* Call headers1() to get LIST of included files. */
60 if (DEBUG_HEADER) printf("header scan %s\n", t->name);
61 lol_init(&lol);
62 lol_add(&lol, list_new(L0, t->name, 1));
63 lol_add(&lol, headers1(t->boundname, hdrscan));
64 if (lol_get(&lol, 1)) list_free(evaluate_rule(hdrrule->string, &lol, L0));
65 /* Clean up */
66 lol_free(&lol);
71 * headers1() - using regexp, scan a file and build include LIST
73 static LIST *headers1 (const char *file, LIST *hdrscan) {
74 FILE *f;
75 int i;
76 int rec = 0;
77 LIST *result = 0;
78 regexp *re[MAXINC];
79 regexp *re_macros;
80 char buf[1024];
82 if (!(f = fopen(file, "r"))) return result;
83 while (rec < MAXINC && hdrscan) {
84 re[rec++] = regcomp(hdrscan->string);
85 hdrscan = list_next(hdrscan);
87 /* the following regexp is used to detect cases where a */
88 /* file is included through a line line "#include MACRO" */
89 re_macros = regcomp("^[ ]*#[ ]*include[ ]*([A-Za-z][A-Za-z0-9_]*).*$");
90 while (fgets(buf, sizeof(buf), f)) {
91 for (i = 0; i < rec; i++) {
92 if (regexec(re[i], buf) && re[i]->startp[1]) {
93 /* Copy and terminate extracted string. */
94 char buf2[MAXSYM];
95 int l = re[i]->endp[1]-re[i]->startp[1];
97 memcpy(buf2, re[i]->startp[1], l);
98 buf2[l] = 0;
99 result = list_new(result, buf2, 0);
100 if (DEBUG_HEADER) printf("header found: %s\n", buf2);
103 /* special treatment for #include MACRO */
104 if (regexec(re_macros, buf) && re_macros->startp[1]) {
105 const char *header_filename;
106 char buf2[MAXSYM];
107 int l = re_macros->endp[1]-re_macros->startp[1];
109 memcpy(buf2, re_macros->startp[1], l);
110 buf2[l] = 0;
111 if (DEBUG_HEADER) printf("macro header found: %s", buf2);
112 header_filename = macro_header_get(buf2);
113 if (header_filename) {
114 if (DEBUG_HEADER) printf(" resolved to '%s'\n", header_filename);
115 result = list_new(result, header_filename, 0);
116 } else {
117 if (DEBUG_HEADER) printf(" ignored !!\n");
121 free(re_macros);
122 while(rec) free((char*)re[--rec]);
123 fclose(f);
125 return result;