Portability cleanup as required by Linus.
[linux-2.6/linux-mips.git] / scripts / mkdep.c
blobb11406cdbb415db1404e3595070d753a5c4c4fa2
1 /*
2 * Originally by Linus Torvalds.
3 * Smart CONFIG_* processing by Werner Almesberger, Michael Chastain.
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.
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.
27 #include <ctype.h>
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
34 #include <sys/fcntl.h>
35 #include <sys/mman.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
41 char __depname[512] = "\n\t@touch ";
42 #define depname (__depname+9)
43 int hasdep;
45 struct path_struct {
46 int len;
47 char buffer[256-sizeof(int)];
48 } path_array[2] = {
49 { 0, "" },
50 { 0, "" }
54 /* Current input file */
55 static const char *g_filename;
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.
63 char * str_config = NULL;
64 int size_config = 0;
65 int len_config = 0;
67 static void
68 do_depname(void)
70 if (!hasdep) {
71 hasdep = 1;
72 printf("%s:", depname);
73 if (g_filename)
74 printf(" %s", g_filename);
79 * Grow the configuration string to a desired length.
80 * Usually the first growth is plenty.
82 void grow_config(int len)
84 if (str_config == NULL) {
85 len_config = 0;
86 size_config = 4096;
87 str_config = malloc(4096);
88 if (str_config == NULL)
89 { perror("malloc"); exit(1); }
92 while (len_config + len > size_config) {
93 str_config = realloc(str_config, size_config *= 2);
94 if (str_config == NULL)
95 { perror("malloc config"); exit(1); }
102 * Lookup a value in the configuration string.
104 int is_defined_config(const char * name, int len)
106 const char * pconfig;
107 const char * plast = str_config + len_config - len;
108 for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
109 if (pconfig[ -1] == '\n'
110 && pconfig[len] == '\n'
111 && !memcmp(pconfig, name, len))
112 return 1;
114 return 0;
120 * Add a new value to the configuration string.
122 void define_config(const char * name, int len)
124 grow_config(len + 1);
126 memcpy(str_config+len_config, name, len);
127 len_config += len;
128 str_config[len_config++] = '\n';
134 * Clear the set of configuration strings.
136 void clear_config(void)
138 len_config = 0;
139 define_config("", 0);
145 * This records all the precious .h filenames. No need for a hash,
146 * it's a long string of values enclosed in tab and newline.
148 char * str_precious = NULL;
149 int size_precious = 0;
150 int len_precious = 0;
155 * Grow the precious string to a desired length.
156 * Usually the first growth is plenty.
158 void grow_precious(int len)
160 if (str_precious == NULL) {
161 len_precious = 0;
162 size_precious = 4096;
163 str_precious = malloc(4096);
164 if (str_precious == NULL)
165 { perror("malloc precious"); exit(1); }
168 while (len_precious + len > size_precious) {
169 str_precious = realloc(str_precious, size_precious *= 2);
170 if (str_precious == NULL)
171 { perror("malloc"); exit(1); }
178 * Add a new value to the precious string.
180 void define_precious(const char * filename)
182 int len = strlen(filename);
183 grow_precious(len + 4);
184 *(str_precious+len_precious++) = '\t';
185 memcpy(str_precious+len_precious, filename, len);
186 len_precious += len;
187 memcpy(str_precious+len_precious, " \\\n", 3);
188 len_precious += 3;
194 * Handle an #include line.
196 void handle_include(int type, const char * name, int len)
198 struct path_struct *path = path_array+type;
200 if (len == 14 && !memcmp(name, "linux/config.h", len))
201 return;
203 if (len >= 7 && !memcmp(name, "config/", 7))
204 define_config(name+7, len-7-2);
206 memcpy(path->buffer+path->len, name, len);
207 path->buffer[path->len+len] = '\0';
208 if (access(path->buffer, F_OK) != 0)
209 return;
211 do_depname();
212 printf(" \\\n %s", path->buffer);
218 * Record the use of a CONFIG_* word.
220 void use_config(const char * name, int len)
222 char *pc;
223 int i;
225 pc = path_array[0].buffer + path_array[0].len;
226 memcpy(pc, "config/", 7);
227 pc += 7;
229 for (i = 0; i < len; i++) {
230 char c = name[i];
231 if (isupper((int)c)) c = tolower((int)c);
232 if (c == '_') c = '/';
233 pc[i] = c;
235 pc[len] = '\0';
237 if (is_defined_config(pc, len))
238 return;
240 define_config(pc, len);
242 do_depname();
243 printf(" \\\n $(wildcard %s.h)", path_array[0].buffer);
249 * Macros for stunningly fast map-based character access.
250 * __buf is a register which holds the current word of the input.
251 * Thus, there is one memory access per sizeof(unsigned long) characters.
254 #if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__MIPSEL__) \
255 || defined(__arm__)
256 #define LE_MACHINE
257 #endif
259 #ifdef LE_MACHINE
260 #define next_byte(x) (x >>= 8)
261 #define current ((unsigned char) __buf)
262 #else
263 #define next_byte(x) (x <<= 8)
264 #define current (__buf >> 8*(sizeof(unsigned long)-1))
265 #endif
267 #define GETNEXT { \
268 next_byte(__buf); \
269 if ((unsigned long) next % sizeof(unsigned long) == 0) { \
270 if (next >= end) \
271 break; \
272 __buf = * (unsigned long *) next; \
274 next++; \
278 * State machine macros.
280 #define CASE(c,label) if (current == c) goto label
281 #define NOTCASE(c,label) if (current != c) goto label
284 * Yet another state machine speedup.
286 #define MAX2(a,b) ((a)>(b)?(a):(b))
287 #define MIN2(a,b) ((a)<(b)?(a):(b))
288 #define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e)))))
289 #define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e)))))
294 * The state machine looks for (approximately) these Perl regular expressions:
296 * m|\/\*.*?\*\/|
297 * m|'.*?'|
298 * m|".*?"|
299 * m|#\s*include\s*"(.*?)"|
300 * m|#\s*include\s*<(.*?>"|
301 * m|#\s*(?define|undef)\s*CONFIG_(\w*)|
302 * m|(?!\w)CONFIG_|
304 * About 98% of the CPU time is spent here, and most of that is in
305 * the 'start' paragraph. Because the current characters are
306 * in a register, the start loop usually eats 4 or 8 characters
307 * per memory read. The MAX5 and MIN5 tests dispose of most
308 * input characters with 1 or 2 comparisons.
310 void state_machine(const char * map, const char * end)
312 const char * next = map;
313 const char * map_dot;
314 unsigned long __buf = 0;
316 for (;;) {
317 start:
318 GETNEXT
319 __start:
320 if (current > MAX5('/','\'','"','#','C')) goto start;
321 if (current < MIN5('/','\'','"','#','C')) goto start;
322 CASE('/', slash);
323 CASE('\'', squote);
324 CASE('"', dquote);
325 CASE('#', pound);
326 CASE('C', cee);
327 goto start;
329 /* / */
330 slash:
331 GETNEXT
332 NOTCASE('*', __start);
333 slash_star_dot_star:
334 GETNEXT
335 __slash_star_dot_star:
336 NOTCASE('*', slash_star_dot_star);
337 GETNEXT
338 NOTCASE('/', __slash_star_dot_star);
339 goto start;
341 /* '.*?' */
342 squote:
343 GETNEXT
344 CASE('\'', start);
345 NOTCASE('\\', squote);
346 GETNEXT
347 goto squote;
349 /* ".*?" */
350 dquote:
351 GETNEXT
352 CASE('"', start);
353 NOTCASE('\\', dquote);
354 GETNEXT
355 goto dquote;
357 /* #\s* */
358 pound:
359 GETNEXT
360 CASE(' ', pound);
361 CASE('\t', pound);
362 CASE('i', pound_i);
363 CASE('d', pound_d);
364 CASE('u', pound_u);
365 goto __start;
367 /* #\s*i */
368 pound_i:
369 GETNEXT NOTCASE('n', __start);
370 GETNEXT NOTCASE('c', __start);
371 GETNEXT NOTCASE('l', __start);
372 GETNEXT NOTCASE('u', __start);
373 GETNEXT NOTCASE('d', __start);
374 GETNEXT NOTCASE('e', __start);
375 goto pound_include;
377 /* #\s*include\s* */
378 pound_include:
379 GETNEXT
380 CASE(' ', pound_include);
381 CASE('\t', pound_include);
382 map_dot = next;
383 CASE('"', pound_include_dquote);
384 CASE('<', pound_include_langle);
385 goto __start;
387 /* #\s*include\s*"(.*)" */
388 pound_include_dquote:
389 GETNEXT
390 CASE('\n', start);
391 NOTCASE('"', pound_include_dquote);
392 handle_include(1, map_dot, next - map_dot - 1);
393 goto start;
395 /* #\s*include\s*<(.*)> */
396 pound_include_langle:
397 GETNEXT
398 CASE('\n', start);
399 NOTCASE('>', pound_include_langle);
400 handle_include(0, map_dot, next - map_dot - 1);
401 goto start;
403 /* #\s*d */
404 pound_d:
405 GETNEXT NOTCASE('e', __start);
406 GETNEXT NOTCASE('f', __start);
407 GETNEXT NOTCASE('i', __start);
408 GETNEXT NOTCASE('n', __start);
409 GETNEXT NOTCASE('e', __start);
410 goto pound_define_undef;
412 /* #\s*u */
413 pound_u:
414 GETNEXT NOTCASE('n', __start);
415 GETNEXT NOTCASE('d', __start);
416 GETNEXT NOTCASE('e', __start);
417 GETNEXT NOTCASE('f', __start);
418 goto pound_define_undef;
421 * #\s*(define|undef)\s*CONFIG_(\w*)
423 * this does not define the word, because it could be inside another
424 * conditional (#if 0). But I do parse the word so that this instance
425 * does not count as a use. -- mec
427 pound_define_undef:
428 GETNEXT
429 CASE(' ', pound_define_undef);
430 CASE('\t', pound_define_undef);
432 NOTCASE('C', __start);
433 GETNEXT NOTCASE('O', __start);
434 GETNEXT NOTCASE('N', __start);
435 GETNEXT NOTCASE('F', __start);
436 GETNEXT NOTCASE('I', __start);
437 GETNEXT NOTCASE('G', __start);
438 GETNEXT NOTCASE('_', __start);
440 map_dot = next;
441 pound_define_undef_CONFIG_word:
442 GETNEXT
443 if (isalnum(current) || current == '_')
444 goto pound_define_undef_CONFIG_word;
445 goto __start;
447 /* \<CONFIG_(\w*) */
448 cee:
449 if (next >= map+2 && (isalnum((int)next[-2]) || next[-2] == '_'))
450 goto start;
451 GETNEXT NOTCASE('O', __start);
452 GETNEXT NOTCASE('N', __start);
453 GETNEXT NOTCASE('F', __start);
454 GETNEXT NOTCASE('I', __start);
455 GETNEXT NOTCASE('G', __start);
456 GETNEXT NOTCASE('_', __start);
458 map_dot = next;
459 cee_CONFIG_word:
460 GETNEXT
461 if (isalnum(current) || current == '_')
462 goto cee_CONFIG_word;
463 use_config(map_dot, next - map_dot - 1);
464 goto __start;
471 * Generate dependencies for one file.
473 void do_depend(const char * filename, const char * command)
475 int mapsize;
476 int pagesizem1 = getpagesize()-1;
477 int fd;
478 struct stat st;
479 char * map;
481 fd = open(filename, O_RDONLY);
482 if (fd < 0) {
483 perror(filename);
484 return;
487 fstat(fd, &st);
488 if (st.st_size == 0) {
489 fprintf(stderr,"%s is empty\n",filename);
490 close(fd);
491 return;
494 mapsize = st.st_size;
495 mapsize = (mapsize+pagesizem1) & ~pagesizem1;
496 map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
497 if ((long) map == -1) {
498 perror("mkdep: mmap");
499 close(fd);
500 return;
502 if ((unsigned long) map % sizeof(unsigned long) != 0)
504 fprintf(stderr, "do_depend: map not aligned\n");
505 exit(1);
508 hasdep = 0;
509 clear_config();
510 state_machine(map, map+st.st_size);
511 if (hasdep) {
512 puts(command);
513 if (*command)
514 define_precious(filename);
517 munmap(map, mapsize);
518 close(fd);
524 * Generate dependencies for all files.
526 int main(int argc, char **argv)
528 int len;
529 char *hpath;
531 hpath = getenv("HPATH");
532 if (!hpath) {
533 fputs("mkdep: HPATH not set in environment. "
534 "Don't bypass the top level Makefile.\n", stderr);
535 return 1;
537 len = strlen(hpath);
538 memcpy(path_array[0].buffer, hpath, len);
539 if (len && hpath[len-1] != '/')
540 path_array[0].buffer[len++] = '/';
541 path_array[0].buffer[len] = '\0';
542 path_array[0].len = len;
544 while (--argc > 0) {
545 const char * filename = *++argv;
546 const char * command = __depname;
547 g_filename = 0;
548 len = strlen(filename);
549 memcpy(depname, filename, len+1);
550 if (len > 2 && filename[len-2] == '.') {
551 if (filename[len-1] == 'c' || filename[len-1] == 'S') {
552 depname[len-1] = 'o';
553 g_filename = filename;
554 command = "";
557 do_depend(filename, command);
559 if (len_precious) {
560 *(str_precious+len_precious) = '\0';
561 printf(".PRECIOUS:%s\n", str_precious);
563 return 0;