1 /*
2 * Originally by Linus Torvalds.
3 * Smart CONFIG_* processing by Werner Almesberger, Michael Chastain.
4 *
5 * Usage: mkdep file ...
6 *
7 * Read source files and output makefile dependency lines for them.
8 * I make simple dependency lines for #include <*.h> and #include "*.h".
9 * I also find instances of CONFIG_FOO and generate dependencies
10 * like include/config/foo.h.
11 *
12 * 1 August 1999, Michael Elizabeth Chastain, <mec@shout.net>
13 * - Keith Owens reported a bug in smart config processing. There used
14 * to be an optimization for "#define CONFIG_FOO ... #ifdef CONFIG_FOO",
15 * so that the file would not depend on CONFIG_FOO because the file defines
16 * this symbol itself. But this optimization is bogus! Consider this code:
17 * "#if 0 \n #define CONFIG_FOO \n #endif ... #ifdef CONFIG_FOO". Here
18 * the definition is inactivated, but I still used it. It turns out this
19 * actually happens a few times in the kernel source. The simple way to
20 * fix this problem is to remove this particular optimization.
21 *
22 * 2.3.99-pre1, Andrew Morton <andrewm@uow.edu.au>
23 * - Changed so that 'filename.o' depends upon 'filename.[cS]'. This is so that
24 * missing source files are noticed, rather than silently ignored.
25 */
26
27 #include <ctype.h>
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 #include <sys/fcntl.h>
35 #include <sys/mman.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38
39
40
41 char __depname[512] = "\n\t@touch ";
42 #define depname (__depname+9)
43 int hasdep;
44
45 struct path_struct {
46 int len;
47 char buffer[256-sizeof(int)];
48 } path_array[2] = {
49 { 0, "" },
50 { 0, "" }
51 };
52
53
54 /* Current input file */
55 static const char *g_filename;
56
57 /*
58 * This records all the configuration options seen.
59 * In perl this would be a hash, but here it's a long string
60 * of values separated by newlines. This is simple and
61 * extremely fast.
62 */
63 char * str_config = NULL;
64 int size_config = 0;
65 int len_config = 0;
66
67 static void
68 do_depname(void)
69 {
70 if (!hasdep) {
71 hasdep = 1;
72 printf("%s:", depname);
73 if (g_filename)
74 printf(" %s", g_filename);
75 }
76 }
77
78 /*
79 * Grow the configuration string to a desired length.
80 * Usually the first growth is plenty.
81 */
82 void grow_config(int len)
83 {
84 while (len_config + len > size_config) {
85 if (size_config == 0)
86 size_config = 2048;
87 str_config = realloc(str_config, size_config *= 2);
88 if (str_config == NULL)
89 { perror("malloc config"); exit(1); }
90 }
91 }
92
93
94
95 /*
96 * Lookup a value in the configuration string.
97 */
98 int is_defined_config(const char * name, int len)
99 {
100 const char * pconfig;
101 const char * plast = str_config + len_config - len;
102 for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
103 if (pconfig[ -1] == '\n'
104 && pconfig[len] == '\n'
105 && !memcmp(pconfig, name, len))
106 return 1;
107 }
108 return 0;
109 }
110
111
112
113 /*
114 * Add a new value to the configuration string.
115 */
116 void define_config(const char * name, int len)
117 {
118 grow_config(len + 1);
119
120 memcpy(str_config+len_config, name, len);
121 len_config += len;
122 str_config[len_config++] = '\n';
123 }
124
125
126
127 /*
128 * Clear the set of configuration strings.
129 */
130 void clear_config(void)
131 {
132 len_config = 0;
133 define_config("", 0);
134 }
135
136
137
138 /*
139 * This records all the precious .h filenames. No need for a hash,
140 * it's a long string of values enclosed in tab and newline.
141 */
142 char * str_precious = NULL;
143 int size_precious = 0;
144 int len_precious = 0;
145
146
147
148 /*
149 * Grow the precious string to a desired length.
150 * Usually the first growth is plenty.
151 */
152 void grow_precious(int len)
153 {
154 while (len_precious + len > size_precious) {
155 if (size_precious == 0)
156 size_precious = 2048;
157 str_precious = realloc(str_precious, size_precious *= 2);
158 if (str_precious == NULL)
159 { perror("malloc"); exit(1); }
160 }
161 }
162
163
164
165 /*
166 * Add a new value to the precious string.
167 */
168 void define_precious(const char * filename)
169 {
170 int len = strlen(filename);
171 grow_precious(len + 4);
172 *(str_precious+len_precious++) = '\t';
173 memcpy(str_precious+len_precious, filename, len);
174 len_precious += len;
175 memcpy(str_precious+len_precious, " \\\n", 3);
176 len_precious += 3;
177 }
178
179
180
181 /*
182 * Handle an #include line.
183 */
184 void handle_include(int type, const char * name, int len)
185 {
186 struct path_struct *path = path_array+type;
187
188 if (len == 14 && !memcmp(name, "linux/config.h", len))
189 return;
190
191 if (len >= 7 && !memcmp(name, "config/", 7))
192 define_config(name+7, len-7-2);
193
194 memcpy(path->buffer+path->len, name, len);
195 path->buffer[path->len+len] = '\0';
196 if (access(path->buffer, F_OK) != 0)
197 return;
198
199 do_depname();
200 printf(" \\\n %s", path->buffer);
201 }
202
203
204
205 /*
206 * Record the use of a CONFIG_* word.
207 */
208 void 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 do_depname();
231 printf(" \\\n $(wildcard %s.h)", path_array[0].buffer);
232 }
233
234
235
236 /*
237 * Macros for stunningly fast map-based character access.
238 * __buf is a register which holds the current word of the input.
239 * Thus, there is one memory access per sizeof(unsigned long) characters.
240 */
241
242 #if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__MIPSEL__) \
243 || defined(__arm__)
244 #define LE_MACHINE
245 #endif
246
247 #ifdef LE_MACHINE
248 #define next_byte(x) (x >>= 8)
249 #define current ((unsigned char) __buf)
250 #else
251 #define next_byte(x) (x <<= 8)
252 #define current (__buf >> 8*(sizeof(unsigned long)-1))
253 #endif
254
255 #define GETNEXT { \
256 next_byte(__buf); \
257 if ((unsigned long) next % sizeof(unsigned long) == 0) { \
258 if (next >= end) \
259 break; \
260 __buf = * (unsigned long *) next; \
261 } \
262 next++; \
263 }
264
265 /*
266 * State machine macros.
267 */
268 #define CASE(c,label) if (current == c) goto label
269 #define NOTCASE(c,label) if (current != c) goto label
270
271 /*
272 * Yet another state machine speedup.
273 */
274 #define MAX2(a,b) ((a)>(b)?(a):(b))
275 #define MIN2(a,b) ((a)<(b)?(a):(b))
276 #define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e)))))
277 #define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e)))))
278
279
280
281 /*
282 * The state machine looks for (approximately) these Perl regular expressions:
283 *
284 * m|\/\*.*?\*\/|
285 * m|\/\/.*|
286 * m|'.*?'|
287 * m|".*?"|
288 * m|#\s*include\s*"(.*?)"|
289 * m|#\s*include\s*<(.*?>"|
290 * m|#\s*(?define|undef)\s*CONFIG_(\w*)|
291 * m|(?!\w)CONFIG_|
292 *
293 * About 98% of the CPU time is spent here, and most of that is in
294 * the 'start' paragraph. Because the current characters are
295 * in a register, the start loop usually eats 4 or 8 characters
296 * per memory read. The MAX5 and MIN5 tests dispose of most
297 * input characters with 1 or 2 comparisons.
298 */
299 void state_machine(const char * map, const char * end)
300 {
301 const char * next = map;
302 const char * map_dot;
303 unsigned long __buf = 0;
304
305 for (;;) {
306 start:
307 GETNEXT
308 __start:
309 if (current > MAX5('/','\'','"','#','C')) goto start;
310 if (current < MIN5('/','\'','"','#','C')) goto start;
311 CASE('/', slash);
312 CASE('\'', squote);
313 CASE('"', dquote);
314 CASE('#', pound);
315 CASE('C', cee);
316 goto start;
317
318 /* // */
319 slash_slash:
320 GETNEXT
321 CASE('\n', start);
322 NOTCASE('\\', slash_slash);
323 GETNEXT
324 goto slash_slash;
325
326 /* / */
327 slash:
328 GETNEXT
329 CASE('/', slash_slash);
330 NOTCASE('*', __start);
331 slash_star_dot_star:
332 GETNEXT
333 __slash_star_dot_star:
334 NOTCASE('*', slash_star_dot_star);
335 GETNEXT
336 NOTCASE('/', __slash_star_dot_star);
337 goto start;
338
339 /* '.*?' */
340 squote:
341 GETNEXT
342 CASE('\'', start);
343 NOTCASE('\\', squote);
344 GETNEXT
345 goto squote;
346
347 /* ".*?" */
348 dquote:
349 GETNEXT
350 CASE('"', start);
351 NOTCASE('\\', dquote);
352 GETNEXT
353 goto dquote;
354
355 /* #\s* */
356 pound:
357 GETNEXT
358 CASE(' ', pound);
359 CASE('\t', pound);
360 CASE('i', pound_i);
361 CASE('d', pound_d);
362 CASE('u', pound_u);
363 goto __start;
364
365 /* #\s*i */
366 pound_i:
367 GETNEXT NOTCASE('n', __start);
368 GETNEXT NOTCASE('c', __start);
369 GETNEXT NOTCASE('l', __start);
370 GETNEXT NOTCASE('u', __start);
371 GETNEXT NOTCASE('d', __start);
372 GETNEXT NOTCASE('e', __start);
373 goto pound_include;
374
375 /* #\s*include\s* */
376 pound_include:
377 GETNEXT
378 CASE(' ', pound_include);
379 CASE('\t', pound_include);
380 map_dot = next;
381 CASE('"', pound_include_dquote);
382 CASE('<', pound_include_langle);
383 goto __start;
384
385 /* #\s*include\s*"(.*)" */
386 pound_include_dquote:
387 GETNEXT
388 CASE('\n', start);
389 NOTCASE('"', pound_include_dquote);
390 handle_include(1, map_dot, next - map_dot - 1);
391 goto start;
392
393 /* #\s*include\s*<(.*)> */
394 pound_include_langle:
395 GETNEXT
396 CASE('\n', start);
397 NOTCASE('>', pound_include_langle);
398 handle_include(0, map_dot, next - map_dot - 1);
399 goto start;
400
401 /* #\s*d */
402 pound_d:
403 GETNEXT NOTCASE('e', __start);
404 GETNEXT NOTCASE('f', __start);
405 GETNEXT NOTCASE('i', __start);
406 GETNEXT NOTCASE('n', __start);
407 GETNEXT NOTCASE('e', __start);
408 goto pound_define_undef;
409
410 /* #\s*u */
411 pound_u:
412 GETNEXT NOTCASE('n', __start);
413 GETNEXT NOTCASE('d', __start);
414 GETNEXT NOTCASE('e', __start);
415 GETNEXT NOTCASE('f', __start);
416 goto pound_define_undef;
417
418 /*
419 * #\s*(define|undef)\s*CONFIG_(\w*)
420 *
421 * this does not define the word, because it could be inside another
422 * conditional (#if 0). But I do parse the word so that this instance
423 * does not count as a use. -- mec
424 */
425 pound_define_undef:
426 GETNEXT
427 CASE(' ', pound_define_undef);
428 CASE('\t', pound_define_undef);
429
430 NOTCASE('C', __start);
431 GETNEXT NOTCASE('O', __start);
432 GETNEXT NOTCASE('N', __start);
433 GETNEXT NOTCASE('F', __start);
434 GETNEXT NOTCASE('I', __start);
435 GETNEXT NOTCASE('G', __start);
436 GETNEXT NOTCASE('_', __start);
437
438 map_dot = next;
439 pound_define_undef_CONFIG_word:
440 GETNEXT
441 if (isalnum(current) || current == '_')
442 goto pound_define_undef_CONFIG_word;
443 goto __start;
444
445 /* \<CONFIG_(\w*) */
446 cee:
447 if (next >= map+2 && (isalnum(next[-2]) || next[-2] == '_'))
448 goto start;
449 GETNEXT NOTCASE('O', __start);
450 GETNEXT NOTCASE('N', __start);
451 GETNEXT NOTCASE('F', __start);
452 GETNEXT NOTCASE('I', __start);
453 GETNEXT NOTCASE('G', __start);
454 GETNEXT NOTCASE('_', __start);
455
456 map_dot = next;
457 cee_CONFIG_word:
458 GETNEXT
459 if (isalnum(current) || current == '_')
460 goto cee_CONFIG_word;
461 use_config(map_dot, next - map_dot - 1);
462 goto __start;
463 }
464 }
465
466
467
468 /*
469 * Generate dependencies for one file.
470 */
471 void do_depend(const char * filename, const char * command)
472 {
473 int mapsize;
474 int pagesizem1 = getpagesize()-1;
475 int fd;
476 struct stat st;
477 char * map;
478
479 fd = open(filename, O_RDONLY);
480 if (fd < 0) {
481 perror(filename);
482 return;
483 }
484
485 fstat(fd, &st);
486 if (st.st_size == 0) {
487 fprintf(stderr,"%s is empty\n",filename);
488 close(fd);
489 return;
490 }
491
492 mapsize = st.st_size;
493 mapsize = (mapsize+pagesizem1) & ~pagesizem1;
494 map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
495 if ((long) map == -1) {
496 perror("mkdep: mmap");
497 close(fd);
498 return;
499 }
500 if ((unsigned long) map % sizeof(unsigned long) != 0)
501 {
502 fprintf(stderr, "do_depend: map not aligned\n");
503 exit(1);
504 }
505
506 hasdep = 0;
507 clear_config();
508 state_machine(map, map+st.st_size);
509 if (hasdep) {
510 puts(command);
511 if (*command)
512 define_precious(filename);
513 }
514
515 munmap(map, mapsize);
516 close(fd);
517 }
518
519
520
521 /*
522 * Generate dependencies for all files.
523 */
524 int main(int argc, char **argv)
525 {
526 int len;
527 char *hpath;
528
529 hpath = getenv("HPATH");
530 if (!hpath) {
531 fputs("mkdep: HPATH not set in environment. "
532 "Don't bypass the top level Makefile.\n", stderr);
533 return 1;
534 }
535 len = strlen(hpath);
536 memcpy(path_array[0].buffer, hpath, len);
537 if (len && hpath[len-1] != '/')
538 path_array[0].buffer[len++] = '/';
539 path_array[0].buffer[len] = '\0';
540 path_array[0].len = len;
541
542 while (--argc > 0) {
543 const char * filename = *++argv;
544 const char * command = __depname;
545 g_filename = 0;
546 len = strlen(filename);
547 memcpy(depname, filename, len+1);
548 if (len > 2 && filename[len-2] == '.') {
549 if (filename[len-1] == 'c' || filename[len-1] == 'S') {
550 depname[len-1] = 'o';
551 g_filename = filename;
552 command = "";
553 }
554 }
555 do_depend(filename, command);
556 }
557 if (len_precious) {
558 *(str_precious+len_precious) = '\0';
559 printf(".PRECIOUS:%s\n", str_precious);
560 }
561 return 0;
562 }
563
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.