removed some OS/2 remnants
[k8jam.git] / src / headers.c
blobc57d2d06919d2759d42bd33533d80c653bb8117b
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().
31 #include "jam.h"
32 #include "lists.h"
33 #include "parse.h"
34 #include "compile.h"
35 #include "rules.h"
36 #include "variable.h"
37 #include "re9.h"
38 #include "headers.h"
39 #include "newstr.h"
40 #include "hdrmacro.h"
41 #include "hcache.h"
42 #include "dstrings.h"
46 #ifndef OPT_HEADER_CACHE_EXT
47 static LIST *headers1 (const char *file, LIST *hdrscan);
48 #endif
53 * headers() - scan a target for include files and call HDRRULE
55 #define MAXINC (10)
57 void headers (TARGET *t) {
58 LIST *hdrscan;
59 LIST *hdrrule;
60 LOL lol;
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);
66 lol_init(&lol);
67 lol_add(&lol, list_new(L0, t->name, 1));
69 #ifdef OPT_HEADER_CACHE_EXT
70 lol_add(&lol, hcache(t, hdrscan));
71 #else
72 lol_add(&lol, headers1(t->boundname, hdrscan));
73 #endif
75 lol_add(&lol, hcache(t, hdrscan));
76 if (lol_get(&lol, 1)) list_free(evaluate_rule(hdrrule->string, &lol, L0));
77 /* clean up */
78 lol_free(&lol);
83 * headers1() - using regexp, scan a file and build include LIST
86 #ifndef OPT_HEADER_CACHE_EXT
87 static
88 #endif
90 LIST *headers1 (const char *file, LIST *hdrscan) {
91 FILE *f;
92 int i;
93 int rec = 0;
94 LIST *result = 0;
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;
99 re9_sub_t mt[4];
100 const char *errmsg;
101 int line_size = 16384;
102 char *buf; /* line_size size */
103 dstring_t buf2;
105 if (DEBUG_HEADER) printf("DBG: trying header [%s]\n", file);
106 if (!(f = fopen(file, "r"))) return result;
107 while (rec < MAXINC && hdrscan) {
108 //printf("header re %d: [%s]\n", rec, hdrscan->string);
109 if ((re[rec] = re9_compile(hdrscan->string, RE9_FLAG_NONUTF8, &errmsg)) == NULL) {
110 printf("FATAL: %s\n", errmsg);
111 exit(42);
113 if ((repp[rec] = re9_prepare(re[rec])) == NULL) {
114 printf("FATAL: out of memory\n");
115 exit(42);
117 ++rec;
118 hdrscan = list_next(hdrscan);
120 /* the following regexp is used to detect cases where a */
121 /* file is included through a line line "#include MACRO" */
122 re_macros = re9_compile("^\\s*#\\s*include\\s+([A-Za-z_][A-Za-z0-9_]*).*$", RE9_FLAG_NONUTF8, &errmsg);
123 if (re_macros == NULL) {
124 printf("FATAL: %s\n", errmsg);
125 exit(42);
127 if ((repp_macros = re9_prepare(re_macros)) == NULL) {
128 printf("FATAL: out of memory\n");
129 exit(42);
131 if (DEBUG_HEADER) printf("header processing: [%s] (%d)\n", file, rec);
133 if ((buf = malloc(line_size)) == NULL) { fprintf(stderr, "FATAL: out of memory!\n"); abort(); }
134 dstr_init(&buf2);
135 while (fgets(buf, line_size, f)) {
136 for (i = 0; i < rec; ++i) {
137 mt[0].sp = mt[0].ep = NULL;
138 if (re9_prepared_execute(repp[i], RE9_FLAG_NONUTF8, buf, mt, 2) > 0 && mt[1].sp != NULL) {
139 /* copy and terminate extracted string */
140 int l = mt[1].ep-mt[1].sp;
141 dstr_clear(&buf2);
142 dstr_push_buf(&buf2, mt[1].sp, l);
143 result = list_new(result, dstr_cstr(&buf2), 0);
144 if (DEBUG_HEADER) printf("header found: %s\n", dstr_cstr(&buf2));
147 /* special treatment for #include MACRO */
148 mt[0].sp = mt[0].ep = NULL;
149 if (re9_prepared_execute(repp_macros, RE9_FLAG_NONUTF8, buf, mt, 2) > 0 && mt[1].sp != NULL) {
150 const char *header_filename;
151 int l = mt[1].ep-mt[1].sp;
152 dstr_clear(&buf2);
153 dstr_push_buf(&buf2, mt[1].sp, l);
154 if (DEBUG_HEADER) printf("macro header found: %s", dstr_cstr(&buf2));
155 header_filename = macro_header_get(dstr_cstr(&buf2));
156 if (header_filename) {
157 if (DEBUG_HEADER) printf(" resolved to '%s'\n", header_filename);
158 result = list_new(result, header_filename, 0);
159 } else {
160 if (DEBUG_HEADER) printf(" ignored !!\n");
164 dstr_done(&buf2);
165 free(buf);
166 fclose(f);
168 re9_prepared_free(repp_macros);
169 re9_free(re_macros);
170 while (--rec >= 0) {
171 re9_prepared_free(repp[rec]);
172 re9_free(re[rec]);
175 return result;