2 * Originally by Linus Torvalds.
3 * Smart CONFIG_* processing by Werner Almesberger, Michael Chastain.
5 * Usage: mkdep cflags -- file ...
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.
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.
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.
26 * 2.4.2-pre3, Keith Owens <kaos@ocs.com.au>
27 * - Accept cflags followed by '--' followed by filenames. mkdep extracts -I
28 * options from cflags and looks in the specified directories as well as the
29 * defaults. Only -I is supported, no attempt is made to handle -idirafter,
41 #include <sys/fcntl.h>
44 #include <sys/types.h>
55 struct path_struct *path_array;
59 /* Current input file */
60 static const char *g_filename;
63 * This records all the configuration options seen.
64 * In perl this would be a hash, but here it's a long string
65 * of values separated by newlines. This is simple and
68 char * str_config = NULL;
78 /* Source file (*.[cS]) */
79 printf("%s:", depname);
80 printf(" %s", g_filename);
82 /* header file (*.h) */
83 printf("dep_%s +=", depname);
89 * Grow the configuration string to a desired length.
90 * Usually the first growth is plenty.
92 void grow_config(int len)
94 while (len_config + len > size_config) {
97 str_config = realloc(str_config, size_config *= 2);
98 if (str_config == NULL)
99 { perror("malloc config"); exit(1); }
106 * Lookup a value in the configuration string.
108 int is_defined_config(const char * name, int len)
110 const char * pconfig;
111 const char * plast = str_config + len_config - len;
112 for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
113 if (pconfig[ -1] == '\n'
114 && pconfig[len] == '\n'
115 && !memcmp(pconfig, name, len))
124 * Add a new value to the configuration string.
126 void define_config(const char * name, int len)
128 grow_config(len + 1);
130 memcpy(str_config+len_config, name, len);
132 str_config[len_config++] = '\n';
138 * Clear the set of configuration strings.
140 void clear_config(void)
143 define_config("", 0);
149 * This records all the precious .h filenames. No need for a hash,
150 * it's a long string of values enclosed in tab and newline.
152 char * str_precious = NULL;
153 int size_precious = 0;
154 int len_precious = 0;
159 * Grow the precious string to a desired length.
160 * Usually the first growth is plenty.
162 void grow_precious(int len)
164 while (len_precious + len > size_precious) {
165 if (size_precious == 0)
166 size_precious = 2048;
167 str_precious = realloc(str_precious, size_precious *= 2);
168 if (str_precious == NULL)
169 { perror("malloc"); exit(1); }
176 * Add a new value to the precious string.
178 void define_precious(const char * filename)
180 int len = strlen(filename);
181 grow_precious(len + 4);
182 *(str_precious+len_precious++) = '\t';
183 memcpy(str_precious+len_precious, filename, len);
185 memcpy(str_precious+len_precious, " \\\n", 3);
192 * Handle an #include line.
194 void handle_include(int start, const char * name, int len)
196 struct path_struct *path;
199 if (len == 14 && !memcmp(name, "include/config.h", len))
202 if (len >= 7 && !memcmp(name, "config/", 7))
203 define_config(name+7, len-7-2);
205 for (i = start, path = path_array+start; i < paths; ++i, ++path) {
206 memcpy(path->buffer+path->len, name, len);
207 path->buffer[path->len+len] = '\0';
208 if (access(path->buffer, F_OK) == 0) {
210 printf(" \\\n %s $(dep_%s)", path->buffer, path->buffer);
220 * Add a path to the list of include paths.
222 void add_path(const char * name)
224 struct path_struct *path;
225 char resolved_path[PATH_MAX+1];
228 if (strcmp(name, ".")) {
229 name2 = realpath(name, resolved_path);
231 fprintf(stderr, "realpath(%s) failed, %m\n", name);
239 path_array = realloc(path_array, (++paths)*sizeof(*path_array));
241 fprintf(stderr, "cannot expand path_arry\n");
245 path = path_array+paths-1;
246 path->len = strlen(name2);
247 path->buffer = malloc(path->len+1+256+1);
249 fprintf(stderr, "cannot allocate path buffer\n");
252 strcpy(path->buffer, name2);
253 if (path->len && *(path->buffer+path->len-1) != '/') {
254 *(path->buffer+path->len) = '/';
255 *(path->buffer+(++(path->len))) = '\0';
262 * Record the use of a CONFIG_* word.
264 void use_config(const char * name, int len)
269 pc = path_array[paths-1].buffer + path_array[paths-1].len;
270 memcpy(pc, "config/", 7);
273 for (i = 0; i < len; i++) {
275 if (isupper((int)c)) c = tolower((int)c);
276 if (c == '_') c = '/';
281 if (is_defined_config(pc, len))
284 define_config(pc, len);
287 printf(" \\\n $(wildcard %s.h)", path_array[paths-1].buffer);
293 * Macros for stunningly fast map-based character access.
294 * __buf is a register which holds the current word of the input.
295 * Thus, there is one memory access per sizeof(unsigned long) characters.
298 #if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__x86_64__) || defined(__MIPSEL__) \
304 #define next_byte(x) (x >>= 8)
305 #define current ((unsigned char) __buf)
307 #define next_byte(x) (x <<= 8)
308 #define current (__buf >> 8*(sizeof(unsigned long)-1))
313 if ((unsigned long) next % sizeof(unsigned long) == 0) { \
316 __buf = * (unsigned long *) next; \
322 * State machine macros.
324 #define CASE(c,label) if (current == c) goto label
325 #define NOTCASE(c,label) if (current != c) goto label
328 * Yet another state machine speedup.
330 #define MAX2(a,b) ((a)>(b)?(a):(b))
331 #define MIN2(a,b) ((a)<(b)?(a):(b))
332 #define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e)))))
333 #define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e)))))
338 * The state machine looks for (approximately) these Perl regular expressions:
344 * m|#\s*include\s*"(.*?)"|
345 * m|#\s*include\s*<(.*?>"|
346 * m|#\s*(?define|undef)\s*CONFIG_(\w*)|
349 * About 98% of the CPU time is spent here, and most of that is in
350 * the 'start' paragraph. Because the current characters are
351 * in a register, the start loop usually eats 4 or 8 characters
352 * per memory read. The MAX5 and MIN5 tests dispose of most
353 * input characters with 1 or 2 comparisons.
355 void state_machine(const char * map, const char * end)
357 const char * next = map;
358 const char * map_dot;
359 unsigned long __buf = 0;
365 if (current > MAX5('/','\'','"','#','C')) goto start;
366 if (current < MIN5('/','\'','"','#','C')) goto start;
378 NOTCASE('\\', slash_slash);
385 CASE('/', slash_slash);
386 NOTCASE('*', __start);
389 __slash_star_dot_star:
390 NOTCASE('*', slash_star_dot_star);
392 NOTCASE('/', __slash_star_dot_star);
399 NOTCASE('\\', squote);
407 NOTCASE('\\', dquote);
423 GETNEXT NOTCASE('n', __start);
424 GETNEXT NOTCASE('c', __start);
425 GETNEXT NOTCASE('l', __start);
426 GETNEXT NOTCASE('u', __start);
427 GETNEXT NOTCASE('d', __start);
428 GETNEXT NOTCASE('e', __start);
434 CASE(' ', pound_include);
435 CASE('\t', pound_include);
437 CASE('"', pound_include_dquote);
438 CASE('<', pound_include_langle);
441 /* #\s*include\s*"(.*)" */
442 pound_include_dquote:
445 NOTCASE('"', pound_include_dquote);
446 handle_include(0, map_dot, next - map_dot - 1);
449 /* #\s*include\s*<(.*)> */
450 pound_include_langle:
453 NOTCASE('>', pound_include_langle);
454 handle_include(1, map_dot, next - map_dot - 1);
459 GETNEXT NOTCASE('e', __start);
460 GETNEXT NOTCASE('f', __start);
461 GETNEXT NOTCASE('i', __start);
462 GETNEXT NOTCASE('n', __start);
463 GETNEXT NOTCASE('e', __start);
464 goto pound_define_undef;
468 GETNEXT NOTCASE('n', __start);
469 GETNEXT NOTCASE('d', __start);
470 GETNEXT NOTCASE('e', __start);
471 GETNEXT NOTCASE('f', __start);
472 goto pound_define_undef;
475 * #\s*(define|undef)\s*CONFIG_(\w*)
477 * this does not define the word, because it could be inside another
478 * conditional (#if 0). But I do parse the word so that this instance
479 * does not count as a use. -- mec
483 CASE(' ', pound_define_undef);
484 CASE('\t', pound_define_undef);
486 NOTCASE('C', __start);
487 GETNEXT NOTCASE('O', __start);
488 GETNEXT NOTCASE('N', __start);
489 GETNEXT NOTCASE('F', __start);
490 GETNEXT NOTCASE('I', __start);
491 GETNEXT NOTCASE('G', __start);
492 GETNEXT NOTCASE('_', __start);
495 pound_define_undef_CONFIG_word:
497 if (isalnum(current) || current == '_')
498 goto pound_define_undef_CONFIG_word;
503 if (next >= map+2 && (isalnum((int)next[-2]) || next[-2] == '_'))
505 GETNEXT NOTCASE('O', __start);
506 GETNEXT NOTCASE('N', __start);
507 GETNEXT NOTCASE('F', __start);
508 GETNEXT NOTCASE('I', __start);
509 GETNEXT NOTCASE('G', __start);
510 GETNEXT NOTCASE('_', __start);
515 if (isalnum(current) || current == '_')
516 goto cee_CONFIG_word;
517 use_config(map_dot, next - map_dot - 1);
525 * Generate dependencies for one file.
527 void do_depend(const char * filename)
530 int pagesizem1 = getpagesize()-1;
535 fd = open(filename, O_RDONLY);
542 if (st.st_size == 0) {
543 fprintf(stderr,"%s is empty\n",filename);
548 mapsize = st.st_size;
549 mapsize = (mapsize+pagesizem1) & ~pagesizem1;
550 map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
551 if ((long) map == -1) {
552 perror("mkdep: mmap");
556 if ((unsigned long) map % sizeof(unsigned long) != 0)
558 fprintf(stderr, "do_depend: map not aligned\n");
564 state_machine(map, map+st.st_size);
569 munmap(map, mapsize);
576 * Generate dependencies for all files.
578 int main(int argc, char **argv)
583 hpath = getenv("TOPDIR");
585 fputs("mkdep: TOPDIR not set in environment. "
586 "Don't bypass the top level Makefile.\n", stderr);
590 add_path("."); /* for #include "..." */
592 while (++argv, --argc > 0) {
593 if (strncmp(*argv, "-I", 2) == 0) {
603 else if (strcmp(*argv, "--") == 0) {
608 add_path(hpath); /* must be last entry, for config files */
611 const char * filename = *++argv;
613 len = strlen(filename);
614 memcpy(depname, filename, len+1);
615 if (len > 2 && filename[len-2] == '.') {
616 if (filename[len-1] == 'c' || filename[len-1] == 'S') {
617 depname[len-1] = 'o';
618 g_filename = filename;
624 *(str_precious+len_precious) = '\0';
625 printf(".PRECIOUS:%s\n", str_precious);