1#include <stdio.h>
2#include <stdlib.h>
3
4#include <errno.h>
5#include <string.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <unistd.h>
9#include <sys/fcntl.h>
10#include <sys/mman.h>
11
12char *filename, *command, __depname[256] = "\n\t@touch ";
13int needsconfig, hasconfig, hasmodules, hasdep;
14
15#define depname (__depname+9)
16
17struct path_struct {
18 int len;
19 char buffer[256-sizeof(int)];
20} path_array[2] = {
21 { 23, "/usr/src/linux/include/" },
22 { 0, "" }
23};
24
25static void handle_include(int type, char *name, int len)
26{
27 int plen;
28 struct path_struct *path = path_array+type;
29
30 if (len == 14)
31 if (!memcmp(name, "linux/config.h", len))
32 hasconfig = 1;
33 else if (!memcmp(name, "linux/module.h", len))
34 hasmodules = 1;
35
36 plen = path->len;
37 memcpy(path->buffer+plen, name, len);
38 len += plen;
39 path->buffer[len] = '\0';
40 if (access(path->buffer, F_OK))
41 return;
42
43 if (!hasdep) {
44 hasdep = 1;
45 printf("%s:", depname);
46 }
47 printf(" \\\n %s", path->buffer);
48}
49
50static void handle_config(void)
51{
52 needsconfig = 1;
53 if (!hasconfig)
54 fprintf(stderr,
55 "%s needs config but has not included config file\n",
56 filename);
57}
58
59#if defined(__alpha__) || defined(__i386__)
60#define LE_MACHINE
61#endif
62
63#ifdef LE_MACHINE
64#define next_byte(x) (x >>= 8)
65#define current ((unsigned char) __buf)
66#else
67#define next_byte(x) (x <<= 8)
68#define current (__buf >> 8*(sizeof(unsigned long)-1))
69#endif
70
71#define GETNEXT { \
72next_byte(__buf); \
73if (!__nrbuf) { \
74 __buf = *(unsigned long *) next; \
75 __nrbuf = sizeof(unsigned long); \
76 if (!__buf) \
77 break; \
78} next++; __nrbuf--; }
79#define CASE(c,label) if (current == c) goto label
80#define NOTCASE(c,label) if (current != c) goto label
81
82static void state_machine(register char *next)
83{
84 for(;;) {
85 register unsigned long __buf = 0;
86 register unsigned long __nrbuf = 0;
87
88normal:
89 GETNEXT
90__normal:
91 CASE('/',slash);
92 CASE('"',string);
93 CASE('\'',char_const);
94 CASE('#',preproc);
95 goto normal;
96
97slash:
98 GETNEXT
99 CASE('*',comment);
100 goto __normal;
101
102string:
103 GETNEXT
104 CASE('"',normal);
105 NOTCASE('\\',string);
106 GETNEXT
107 goto string;
108
109char_const:
110 GETNEXT
111 CASE('\'',normal);
112 NOTCASE('\\',char_const);
113 GETNEXT
114 goto char_const;
115
116comment:
117 GETNEXT
118__comment:
119 NOTCASE('*',comment);
120 GETNEXT
121 CASE('/',normal);
122 goto __comment;
123
124preproc:
125 GETNEXT
126 CASE('\n',normal);
127 CASE(' ',preproc);
128 CASE('\t',preproc);
129 CASE('i',i_preproc);
130 CASE('e',e_preproc);
131 GETNEXT
132
133skippreproc:
134 CASE('\n',normal);
135 CASE('\\',skippreprocslash);
136 GETNEXT
137 goto skippreproc;
138
139skippreprocslash:
140 GETNEXT;
141 GETNEXT;
142 goto skippreproc;
143
144e_preproc:
145 GETNEXT
146 NOTCASE('l',skippreproc);
147 GETNEXT
148 NOTCASE('i',skippreproc);
149 GETNEXT
150 CASE('f',if_line);
151 goto skippreproc;
152
153i_preproc:
154 GETNEXT
155 CASE('f',if_line);
156 NOTCASE('n',skippreproc);
157 GETNEXT
158 NOTCASE('c',skippreproc);
159 GETNEXT
160 NOTCASE('l',skippreproc);
161 GETNEXT
162 NOTCASE('u',skippreproc);
163 GETNEXT
164 NOTCASE('d',skippreproc);
165 GETNEXT
166 NOTCASE('e',skippreproc);
167
168
169include_line:
170 GETNEXT
171 CASE('\n',normal);
172 CASE('<', std_include_file);
173 NOTCASE('"', include_line);
174
175
176{
177 char *incname = next;
178local_include_name:
179 GETNEXT
180 CASE('\n',normal);
181 NOTCASE('"', local_include_name);
182 handle_include(1, incname, next-incname-1);
183 goto skippreproc;
184}
185
186
187std_include_file:
188{
189 char *incname = next;
190std_include_name:
191 GETNEXT
192 CASE('\n',normal);
193 NOTCASE('>', std_include_name);
194 handle_include(0, incname, next-incname-1);
195 goto skippreproc;
196}
197
198if_line:
199 if (needsconfig)
200 goto skippreproc;
201if_start:
202 GETNEXT
203 CASE('C', config);
204 CASE('\n', normal);
205 CASE('_', if_middle);
206 if (current >= 'a' && current <= 'z')
207 goto if_middle;
208 if (current < 'A' || current > 'Z')
209 goto if_start;
210config:
211 GETNEXT
212 NOTCASE('O', __if_middle);
213 GETNEXT
214 NOTCASE('N', __if_middle);
215 GETNEXT
216 NOTCASE('F', __if_middle);
217 GETNEXT
218 NOTCASE('I', __if_middle);
219 GETNEXT
220 NOTCASE('G', __if_middle);
221 GETNEXT
222 NOTCASE('_', __if_middle);
223 handle_config();
224 goto skippreproc;
225
226if_middle:
227 GETNEXT
228__if_middle:
229 CASE('\n', normal);
230 CASE('_', if_middle);
231 if (current >= 'a' && current <= 'z')
232 goto if_middle;
233 if (current < 'A' || current > 'Z')
234 goto if_start;
235 goto if_middle;
236 }
237}
238
239static void do_depend(void)
240{
241 char *map;
242 int mapsize;
243 int pagesizem1 = getpagesize()-1;
244 int fd = open(filename, O_RDONLY);
245 struct stat st;
246
247 if (fd < 0) {
248 if (errno != ENOENT)
249 perror(filename);
250 return;
251 }
252 fstat(fd, &st);
253 if (st.st_size == 0) {
254 fprintf(stderr,"%s is empty\n",filename);
255 return;
256 }
257 mapsize = st.st_size + 2*sizeof(unsigned long);
258 mapsize = (mapsize+pagesizem1) & ~pagesizem1;
259 map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
260 if (-1 == (long)map) {
261 perror("mkdep: mmap");
262 close(fd);
263 return;
264 }
265 close(fd);
266 state_machine(map);
267 munmap(map, mapsize);
268 if (hasdep)
269 puts(command);
270}
271
272int main(int argc, char **argv)
273{
274 int len;
275 char * hpath;
276
277 hpath = getenv("HPATH");
278 if (!hpath)
279 hpath = "/usr/src/linux/include";
280 len = strlen(hpath);
281 memcpy(path_array[0].buffer, hpath, len);
282 if (len && hpath[len-1] != '/') {
283 path_array[0].buffer[len] = '/';
284 len++;
285 }
286 path_array[0].buffer[len] = '\0';
287 path_array[0].len = len;
288
289 while (--argc > 0) {
290 int len;
291 char *name = *++argv;
292
293 filename = name;
294 len = strlen(name);
295 memcpy(depname, name, len+1);
296 command = __depname;
297 if (len > 2 && name[len-2] == '.') {
298 switch (name[len-1]) {
299 case 'c':
300 case 'S':
301 depname[len-1] = 'o';
302 command = "";
303 }
304 }
305 needsconfig = hasconfig = hasmodules = hasdep = 0;
306 do_depend();
307 if (hasconfig && !hasmodules && !needsconfig)
308 fprintf(stderr, "%s doesn't need config\n", filename);
309 }
310 return 0;
311}
312