1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <ctype.h>
24#include <fcntl.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30#include <sys/fcntl.h>
31#include <sys/mman.h>
32#include <sys/stat.h>
33#include <sys/types.h>
34
35
36
37char __depname[512] = "\n\t@touch ";
38#define depname (__depname+9)
39int hasdep;
40
41struct path_struct {
42 int len;
43 char buffer[256-sizeof(int)];
44} path_array[2] = {
45 { 0, "" },
46 { 0, "" }
47};
48
49
50
51
52
53
54
55
56
57char * str_config = NULL;
58int size_config = 0;
59int len_config = 0;
60
61
62
63
64
65
66
67void grow_config(int len)
68{
69 if (str_config == NULL) {
70 len_config = 0;
71 size_config = 4096;
72 str_config = malloc(4096);
73 if (str_config == NULL)
74 { perror("malloc"); exit(1); }
75 }
76
77 while (len_config + len > size_config) {
78 str_config = realloc(str_config, size_config *= 2);
79 if (str_config == NULL)
80 { perror("malloc config"); exit(1); }
81 }
82}
83
84
85
86
87
88
89int is_defined_config(const char * name, int len)
90{
91 const char * pconfig;
92 const char * plast = str_config + len_config - len;
93 for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
94 if (pconfig[ -1] == '\n'
95 && pconfig[len] == '\n'
96 && !memcmp(pconfig, name, len))
97 return 1;
98 }
99 return 0;
100}
101
102
103
104
105
106
107void define_config(const char * name, int len)
108{
109 grow_config(len + 1);
110
111 memcpy(str_config+len_config, name, len);
112 len_config += len;
113 str_config[len_config++] = '\n';
114}
115
116
117
118
119
120
121void clear_config(void)
122{
123 len_config = 0;
124 define_config("", 0);
125}
126
127
128
129
130
131
132
133char * str_precious = NULL;
134int size_precious = 0;
135int len_precious = 0;
136
137
138
139
140
141
142
143void grow_precious(int len)
144{
145 if (str_precious == NULL) {
146 len_precious = 0;
147 size_precious = 4096;
148 str_precious = malloc(4096);
149 if (str_precious == NULL)
150 { perror("malloc precious"); exit(1); }
151 }
152
153 while (len_precious + len > size_precious) {
154 str_precious = realloc(str_precious, size_precious *= 2);
155 if (str_precious == NULL)
156 { perror("malloc"); exit(1); }
157 }
158}
159
160
161
162
163
164
165void define_precious(const char * filename)
166{
167 int len = strlen(filename);
168 grow_precious(len + 4);
169 *(str_precious+len_precious++) = '\t';
170 memcpy(str_precious+len_precious, filename, len);
171 len_precious += len;
172 memcpy(str_precious+len_precious, " \\\n", 3);
173 len_precious += 3;
174}
175
176
177
178
179
180
181void handle_include(int type, const char * name, int len)
182{
183 struct path_struct *path = path_array+type;
184
185 if (len == 14 && !memcmp(name, "linux/config.h", len))
186 return;
187
188 if (len >= 7 && !memcmp(name, "config/", 7))
189 define_config(name+7, len-7-2);
190
191 memcpy(path->buffer+path->len, name, len);
192 path->buffer[path->len+len] = '\0';
193 if (access(path->buffer, F_OK) != 0)
194 return;
195
196 if (!hasdep) {
197 hasdep = 1;
198 printf("%s:", depname);
199 }
200 printf(" \\\n %s", path->buffer);
201}
202
203
204
205
206
207
208void use_config(const char * name, int len)
209{
210 char *pc;
211 int i;
212
213 pc = path_array[0].buffer + path_array[0].len;
214 memcpy(pc, "config/", 7);
215 pc += 7;
216
217 for (i = 0; i < len; i++) {
218 char c = name[i];
219 if (isupper(c)) c = tolower(c);
220 if (c == '_') c = '/';
221 pc[i] = c;
222 }
223 pc[len] = '\0';
224
225 if (is_defined_config(pc, len))
226 return;
227
228 define_config(pc, len);
229
230 if (!hasdep) {
231 hasdep = 1;
232 printf("%s: ", depname);
233 }
234 printf(" \\\n $(wildcard %s.h)", path_array[0].buffer);
235}
236
237
238
239
240
241
242
243
244
245#if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__MIPSEL__) \
246 || defined(__arm__)
247#define LE_MACHINE
248#endif
249
250#ifdef LE_MACHINE
251#define next_byte(x) (x >>= 8)
252#define current ((unsigned char) __buf)
253#else
254#define next_byte(x) (x <<= 8)
255#define current (__buf >> 8*(sizeof(unsigned long)-1))
256#endif
257
258#define GETNEXT { \
259 next_byte(__buf); \
260 if ((unsigned long) next % sizeof(unsigned long) == 0) { \
261 if (next >= end) \
262 break; \
263 __buf = * (unsigned long *) next; \
264 } \
265 next++; \
266}
267
268
269
270
271#define CASE(c,label) if (current == c) goto label
272#define NOTCASE(c,label) if (current != c) goto label
273
274
275
276
277#define MAX2(a,b) ((a)>(b)?(a):(b))
278#define MIN2(a,b) ((a)<(b)?(a):(b))
279#define MAX6(a,b,c,d,e,f) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,MAX2(e,f))))))
280#define MIN6(a,b,c,d,e,f) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,MIN2(e,f))))))
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303void state_machine(const char * map, const char * end)
304{
305 const char * next = map;
306 const char * map_dot;
307 unsigned long __buf = 0;
308
309 for (;;) {
310start:
311 GETNEXT
312__start:
313 if (current > MAX6('/','\'','"','#','C','_')) goto start;
314 if (current < MIN6('/','\'','"','#','C','_')) goto start;
315 CASE('/', slash);
316 CASE('\'', squote);
317 CASE('"', dquote);
318 CASE('#', pound);
319 CASE('C', cee);
320 CASE('_', underscore);
321 goto start;
322
323
324slash_slash:
325 GETNEXT
326 CASE('\n', start);
327 NOTCASE('\\', slash_slash);
328 GETNEXT
329 goto slash_slash;
330
331
332slash:
333 GETNEXT
334 CASE('/', slash_slash);
335 NOTCASE('*', __start);
336slash_star_dot_star:
337 GETNEXT
338__slash_star_dot_star:
339 NOTCASE('*', slash_star_dot_star);
340 GETNEXT
341 NOTCASE('/', __slash_star_dot_star);
342 goto start;
343
344
345squote:
346 GETNEXT
347 CASE('\'', start);
348 NOTCASE('\\', squote);
349 GETNEXT
350 goto squote;
351
352
353dquote:
354 GETNEXT
355 CASE('"', start);
356 NOTCASE('\\', dquote);
357 GETNEXT
358 goto dquote;
359
360
361pound:
362 GETNEXT
363 CASE(' ', pound);
364 CASE('\t', pound);
365 CASE('i', pound_i);
366 CASE('d', pound_d);
367 CASE('u', pound_u);
368 goto __start;
369
370
371pound_i:
372 GETNEXT NOTCASE('n', __start);
373 GETNEXT NOTCASE('c', __start);
374 GETNEXT NOTCASE('l', __start);
375 GETNEXT NOTCASE('u', __start);
376 GETNEXT NOTCASE('d', __start);
377 GETNEXT NOTCASE('e', __start);
378 goto pound_include;
379
380
381pound_include:
382 GETNEXT
383 CASE(' ', pound_include);
384 CASE('\t', pound_include);
385 map_dot = next;
386 CASE('"', pound_include_dquote);
387 CASE('<', pound_include_langle);
388 goto __start;
389
390
391pound_include_dquote:
392 GETNEXT
393 CASE('\n', start);
394 NOTCASE('"', pound_include_dquote);
395 handle_include(1, map_dot, next - map_dot - 1);
396 goto start;
397
398
399pound_include_langle:
400 GETNEXT
401 CASE('\n', start);
402 NOTCASE('>', pound_include_langle);
403 handle_include(0, map_dot, next - map_dot - 1);
404 goto start;
405
406
407pound_d:
408 GETNEXT NOTCASE('e', __start);
409 GETNEXT NOTCASE('f', __start);
410 GETNEXT NOTCASE('i', __start);
411 GETNEXT NOTCASE('n', __start);
412 GETNEXT NOTCASE('e', __start);
413 goto pound_define_undef;
414
415
416pound_u:
417 GETNEXT NOTCASE('n', __start);
418 GETNEXT NOTCASE('d', __start);
419 GETNEXT NOTCASE('e', __start);
420 GETNEXT NOTCASE('f', __start);
421 goto pound_define_undef;
422
423
424
425
426
427
428
429
430pound_define_undef:
431 GETNEXT
432 CASE(' ', pound_define_undef);
433 CASE('\t', pound_define_undef);
434
435 NOTCASE('C', __start);
436 GETNEXT NOTCASE('O', __start);
437 GETNEXT NOTCASE('N', __start);
438 GETNEXT NOTCASE('F', __start);
439 GETNEXT NOTCASE('I', __start);
440 GETNEXT NOTCASE('G', __start);
441 GETNEXT NOTCASE('_', __start);
442
443 map_dot = next;
444pound_define_undef_CONFIG_word:
445 GETNEXT
446 if (isalnum(current) || current == '_')
447 goto pound_define_undef_CONFIG_word;
448 goto __start;
449
450
451cee:
452 if (next >= map+2 && (isalnum(next[-2]) || next[-2] == '_'))
453 goto start;
454 GETNEXT NOTCASE('O', __start);
455 GETNEXT NOTCASE('N', __start);
456 GETNEXT NOTCASE('F', __start);
457 GETNEXT NOTCASE('I', __start);
458 GETNEXT NOTCASE('G', __start);
459 GETNEXT NOTCASE('_', __start);
460
461 map_dot = next;
462cee_CONFIG_word:
463 GETNEXT
464 if (isalnum(current) || current == '_')
465 goto cee_CONFIG_word;
466 use_config(map_dot, next - map_dot - 1);
467 goto __start;
468
469
470underscore:
471 GETNEXT NOTCASE('_', __start);
472 GETNEXT NOTCASE('S', __start);
473 GETNEXT NOTCASE('M', __start);
474 GETNEXT NOTCASE('P', __start);
475 GETNEXT NOTCASE('_', __start);
476 GETNEXT NOTCASE('_', __start);
477 use_config("SMP", 3);
478 goto __start;
479
480 }
481}
482
483
484
485
486
487
488void do_depend(const char * filename, const char * command)
489{
490 int mapsize;
491 int pagesizem1 = getpagesize()-1;
492 int fd;
493 struct stat st;
494 char * map;
495
496 fd = open(filename, O_RDONLY);
497 if (fd < 0) {
498 perror(filename);
499 return;
500 }
501
502 fstat(fd, &st);
503 if (st.st_size == 0) {
504 fprintf(stderr,"%s is empty\n",filename);
505 close(fd);
506 return;
507 }
508
509 mapsize = st.st_size;
510 mapsize = (mapsize+pagesizem1) & ~pagesizem1;
511 map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
512 if ((long) map == -1) {
513 perror("mkdep: mmap");
514 close(fd);
515 return;
516 }
517 if ((unsigned long) map % sizeof(unsigned long) != 0)
518 {
519 fprintf(stderr, "do_depend: map not aligned\n");
520 exit(1);
521 }
522
523 hasdep = 0;
524 clear_config();
525 state_machine(map, map+st.st_size);
526 if (hasdep) {
527 puts(command);
528 if (*command)
529 define_precious(filename);
530 }
531
532 munmap(map, mapsize);
533 close(fd);
534}
535
536
537
538
539
540
541int main(int argc, char **argv)
542{
543 int len;
544 char *hpath;
545
546 hpath = getenv("HPATH");
547 if (!hpath) {
548 fputs("mkdep: HPATH not set in environment. "
549 "Don't bypass the top level Makefile.\n", stderr);
550 return 1;
551 }
552 len = strlen(hpath);
553 memcpy(path_array[0].buffer, hpath, len);
554 if (len && hpath[len-1] != '/')
555 path_array[0].buffer[len++] = '/';
556 path_array[0].buffer[len] = '\0';
557 path_array[0].len = len;
558
559 while (--argc > 0) {
560 const char * filename = *++argv;
561 const char * command = __depname;
562 len = strlen(filename);
563 memcpy(depname, filename, len+1);
564 if (len > 2 && filename[len-2] == '.') {
565 if (filename[len-1] == 'c' || filename[len-1] == 'S') {
566 depname[len-1] = 'o';
567 command = "";
568 }
569 }
570 do_depend(filename, command);
571 }
572 if (len_precious) {
573 *(str_precious+len_precious) = '\0';
574 printf(".PRECIOUS:%s\n", str_precious);
575 }
576 return 0;
577}
578