diff options
Diffstat (limited to 'scripts/mkdep.c')
-rw-r--r-- | scripts/mkdep.c | 628 |
1 files changed, 0 insertions, 628 deletions
diff --git a/scripts/mkdep.c b/scripts/mkdep.c deleted file mode 100644 index ae3cc74e0..000000000 --- a/scripts/mkdep.c +++ /dev/null @@ -1,628 +0,0 @@ -/* - * Originally by Linus Torvalds. - * Smart CONFIG_* processing by Werner Almesberger, Michael Chastain. - * - * Usage: mkdep cflags -- file ... - * - * Read source files and output makefile dependency lines for them. - * I make simple dependency lines for #include <*.h> and #include "*.h". - * I also find instances of CONFIG_FOO and generate dependencies - * like include/config/foo.h. - * - * 1 August 1999, Michael Elizabeth Chastain, <mec@shout.net> - * - Keith Owens reported a bug in smart config processing. There used - * to be an optimization for "#define CONFIG_FOO ... #ifdef CONFIG_FOO", - * so that the file would not depend on CONFIG_FOO because the file defines - * this symbol itself. But this optimization is bogus! Consider this code: - * "#if 0 \n #define CONFIG_FOO \n #endif ... #ifdef CONFIG_FOO". Here - * the definition is inactivated, but I still used it. It turns out this - * actually happens a few times in the kernel source. The simple way to - * fix this problem is to remove this particular optimization. - * - * 2.3.99-pre1, Andrew Morton <andrewm@uow.edu.au> - * - Changed so that 'filename.o' depends upon 'filename.[cS]'. This is so that - * missing source files are noticed, rather than silently ignored. - * - * 2.4.2-pre3, Keith Owens <kaos@ocs.com.au> - * - Accept cflags followed by '--' followed by filenames. mkdep extracts -I - * options from cflags and looks in the specified directories as well as the - * defaults. Only -I is supported, no attempt is made to handle -idirafter, - * -isystem, -I- etc. - */ - -#include <ctype.h> -#include <fcntl.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <sys/fcntl.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> - - - -char depname[512]; -int hasdep; - -struct path_struct { - int len; - char *buffer; -}; -struct path_struct *path_array; -int paths; - - -/* Current input file */ -static const char *g_filename; - -/* - * This records all the configuration options seen. - * In perl this would be a hash, but here it's a long string - * of values separated by newlines. This is simple and - * extremely fast. - */ -char * str_config = NULL; -int size_config = 0; -int len_config = 0; - -static void -do_depname(void) -{ - if (!hasdep) { - hasdep = 1; - if (g_filename) { - /* Source file (*.[cS]) */ - printf("%s:", depname); - printf(" %s", g_filename); - } else { - /* header file (*.h) */ - printf("dep_%s +=", depname); - } - } -} - -/* - * Grow the configuration string to a desired length. - * Usually the first growth is plenty. - */ -void grow_config(int len) -{ - while (len_config + len > size_config) { - if (size_config == 0) - size_config = 2048; - str_config = realloc(str_config, size_config *= 2); - if (str_config == NULL) - { perror("malloc config"); exit(1); } - } -} - - - -/* - * Lookup a value in the configuration string. - */ -int is_defined_config(const char * name, int len) -{ - const char * pconfig; - const char * plast = str_config + len_config - len; - for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) { - if (pconfig[ -1] == '\n' - && pconfig[len] == '\n' - && !memcmp(pconfig, name, len)) - return 1; - } - return 0; -} - - - -/* - * Add a new value to the configuration string. - */ -void define_config(const char * name, int len) -{ - grow_config(len + 1); - - memcpy(str_config+len_config, name, len); - len_config += len; - str_config[len_config++] = '\n'; -} - - - -/* - * Clear the set of configuration strings. - */ -void clear_config(void) -{ - len_config = 0; - define_config("", 0); -} - - - -/* - * This records all the precious .h filenames. No need for a hash, - * it's a long string of values enclosed in tab and newline. - */ -char * str_precious = NULL; -int size_precious = 0; -int len_precious = 0; - - - -/* - * Grow the precious string to a desired length. - * Usually the first growth is plenty. - */ -void grow_precious(int len) -{ - while (len_precious + len > size_precious) { - if (size_precious == 0) - size_precious = 2048; - str_precious = realloc(str_precious, size_precious *= 2); - if (str_precious == NULL) - { perror("malloc"); exit(1); } - } -} - - - -/* - * Add a new value to the precious string. - */ -void define_precious(const char * filename) -{ - int len = strlen(filename); - grow_precious(len + 4); - *(str_precious+len_precious++) = '\t'; - memcpy(str_precious+len_precious, filename, len); - len_precious += len; - memcpy(str_precious+len_precious, " \\\n", 3); - len_precious += 3; -} - - - -/* - * Handle an #include line. - */ -void handle_include(int start, const char * name, int len) -{ - struct path_struct *path; - int i; - - if (len == 14 && !memcmp(name, "include/config.h", len)) - return; - - if (len >= 7 && !memcmp(name, "config/", 7)) - define_config(name+7, len-7-2); - - for (i = start, path = path_array+start; i < paths; ++i, ++path) { - memcpy(path->buffer+path->len, name, len); - path->buffer[path->len+len] = '\0'; - if (access(path->buffer, F_OK) == 0) { - do_depname(); - printf(" \\\n %s $(dep_%s)", path->buffer, path->buffer); - return; - } - } - -} - - - -/* - * Add a path to the list of include paths. - */ -void add_path(const char * name) -{ - struct path_struct *path; - char resolved_path[PATH_MAX+1]; - const char *name2; - - if (strcmp(name, ".")) { - name2 = realpath(name, resolved_path); - if (!name2) { - fprintf(stderr, "realpath(%s) failed, %m\n", name); - exit(1); - } - } - else { - name2 = ""; - } - - path_array = realloc(path_array, (++paths)*sizeof(*path_array)); - if (!path_array) { - fprintf(stderr, "cannot expand path_arry\n"); - exit(1); - } - - path = path_array+paths-1; - path->len = strlen(name2); - path->buffer = malloc(path->len+1+256+1); - if (!path->buffer) { - fprintf(stderr, "cannot allocate path buffer\n"); - exit(1); - } - strcpy(path->buffer, name2); - if (path->len && *(path->buffer+path->len-1) != '/') { - *(path->buffer+path->len) = '/'; - *(path->buffer+(++(path->len))) = '\0'; - } -} - - - -/* - * Record the use of a CONFIG_* word. - */ -void use_config(const char * name, int len) -{ - char *pc; - int i; - - pc = path_array[paths-1].buffer + path_array[paths-1].len; - memcpy(pc, "config/", 7); - pc += 7; - - for (i = 0; i < len; i++) { - char c = name[i]; - if (isupper((int)c)) c = tolower((int)c); - if (c == '_') c = '/'; - pc[i] = c; - } - pc[len] = '\0'; - - if (is_defined_config(pc, len)) - return; - - define_config(pc, len); - - do_depname(); - printf(" \\\n $(wildcard %s.h)", path_array[paths-1].buffer); -} - - - -/* - * Macros for stunningly fast map-based character access. - * __buf is a register which holds the current word of the input. - * Thus, there is one memory access per sizeof(unsigned long) characters. - */ - -#if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__x86_64__) || defined(__MIPSEL__) \ - || defined(__arm__) -#define LE_MACHINE -#endif - -#ifdef LE_MACHINE -#define next_byte(x) (x >>= 8) -#define current ((unsigned char) __buf) -#else -#define next_byte(x) (x <<= 8) -#define current (__buf >> 8*(sizeof(unsigned long)-1)) -#endif - -#define GETNEXT { \ - next_byte(__buf); \ - if ((unsigned long) next % sizeof(unsigned long) == 0) { \ - if (next >= end) \ - break; \ - __buf = * (unsigned long *) next; \ - } \ - next++; \ -} - -/* - * State machine macros. - */ -#define CASE(c,label) if (current == c) goto label -#define NOTCASE(c,label) if (current != c) goto label - -/* - * Yet another state machine speedup. - */ -#define MAX2(a,b) ((a)>(b)?(a):(b)) -#define MIN2(a,b) ((a)<(b)?(a):(b)) -#define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e))))) -#define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e))))) - - - -/* - * The state machine looks for (approximately) these Perl regular expressions: - * - * m|\/\*.*?\*\/| - * m|\/\/.*| - * m|'.*?'| - * m|".*?"| - * m|#\s*include\s*"(.*?)"| - * m|#\s*include\s*<(.*?>"| - * m|#\s*(?define|undef)\s*CONFIG_(\w*)| - * m|(?!\w)CONFIG_| - * - * About 98% of the CPU time is spent here, and most of that is in - * the 'start' paragraph. Because the current characters are - * in a register, the start loop usually eats 4 or 8 characters - * per memory read. The MAX5 and MIN5 tests dispose of most - * input characters with 1 or 2 comparisons. - */ -void state_machine(const char * map, const char * end) -{ - const char * next = map; - const char * map_dot; - unsigned long __buf = 0; - - for (;;) { -start: - GETNEXT -__start: - if (current > MAX5('/','\'','"','#','C')) goto start; - if (current < MIN5('/','\'','"','#','C')) goto start; - CASE('/', slash); - CASE('\'', squote); - CASE('"', dquote); - CASE('#', pound); - CASE('C', cee); - goto start; - -/* // */ -slash_slash: - GETNEXT - CASE('\n', start); - NOTCASE('\\', slash_slash); - GETNEXT - goto slash_slash; - -/* / */ -slash: - GETNEXT - CASE('/', slash_slash); - NOTCASE('*', __start); -slash_star_dot_star: - GETNEXT -__slash_star_dot_star: - NOTCASE('*', slash_star_dot_star); - GETNEXT - NOTCASE('/', __slash_star_dot_star); - goto start; - -/* '.*?' */ -squote: - GETNEXT - CASE('\'', start); - NOTCASE('\\', squote); - GETNEXT - goto squote; - -/* ".*?" */ -dquote: - GETNEXT - CASE('"', start); - NOTCASE('\\', dquote); - GETNEXT - goto dquote; - -/* #\s* */ -pound: - GETNEXT - CASE(' ', pound); - CASE('\t', pound); - CASE('i', pound_i); - CASE('d', pound_d); - CASE('u', pound_u); - goto __start; - -/* #\s*i */ -pound_i: - GETNEXT NOTCASE('n', __start); - GETNEXT NOTCASE('c', __start); - GETNEXT NOTCASE('l', __start); - GETNEXT NOTCASE('u', __start); - GETNEXT NOTCASE('d', __start); - GETNEXT NOTCASE('e', __start); - goto pound_include; - -/* #\s*include\s* */ -pound_include: - GETNEXT - CASE(' ', pound_include); - CASE('\t', pound_include); - map_dot = next; - CASE('"', pound_include_dquote); - CASE('<', pound_include_langle); - goto __start; - -/* #\s*include\s*"(.*)" */ -pound_include_dquote: - GETNEXT - CASE('\n', start); - NOTCASE('"', pound_include_dquote); - handle_include(0, map_dot, next - map_dot - 1); - goto start; - -/* #\s*include\s*<(.*)> */ -pound_include_langle: - GETNEXT - CASE('\n', start); - NOTCASE('>', pound_include_langle); - handle_include(1, map_dot, next - map_dot - 1); - goto start; - -/* #\s*d */ -pound_d: - GETNEXT NOTCASE('e', __start); - GETNEXT NOTCASE('f', __start); - GETNEXT NOTCASE('i', __start); - GETNEXT NOTCASE('n', __start); - GETNEXT NOTCASE('e', __start); - goto pound_define_undef; - -/* #\s*u */ -pound_u: - GETNEXT NOTCASE('n', __start); - GETNEXT NOTCASE('d', __start); - GETNEXT NOTCASE('e', __start); - GETNEXT NOTCASE('f', __start); - goto pound_define_undef; - -/* - * #\s*(define|undef)\s*CONFIG_(\w*) - * - * this does not define the word, because it could be inside another - * conditional (#if 0). But I do parse the word so that this instance - * does not count as a use. -- mec - */ -pound_define_undef: - GETNEXT - CASE(' ', pound_define_undef); - CASE('\t', pound_define_undef); - - NOTCASE('C', __start); - GETNEXT NOTCASE('O', __start); - GETNEXT NOTCASE('N', __start); - GETNEXT NOTCASE('F', __start); - GETNEXT NOTCASE('I', __start); - GETNEXT NOTCASE('G', __start); - GETNEXT NOTCASE('_', __start); - - map_dot = next; -pound_define_undef_CONFIG_word: - GETNEXT - if (isalnum(current) || current == '_') - goto pound_define_undef_CONFIG_word; - goto __start; - -/* \<CONFIG_(\w*) */ -cee: - if (next >= map+2 && (isalnum((int)next[-2]) || next[-2] == '_')) - goto start; - GETNEXT NOTCASE('O', __start); - GETNEXT NOTCASE('N', __start); - GETNEXT NOTCASE('F', __start); - GETNEXT NOTCASE('I', __start); - GETNEXT NOTCASE('G', __start); - GETNEXT NOTCASE('_', __start); - - map_dot = next; -cee_CONFIG_word: - GETNEXT - if (isalnum(current) || current == '_') - goto cee_CONFIG_word; - use_config(map_dot, next - map_dot - 1); - goto __start; - } -} - - - -/* - * Generate dependencies for one file. - */ -void do_depend(const char * filename) -{ - int mapsize; - int pagesizem1 = getpagesize()-1; - int fd; - struct stat st; - char * map; - - fd = open(filename, O_RDONLY); - if (fd < 0) { - perror(filename); - return; - } - - fstat(fd, &st); - if (st.st_size == 0) { - fprintf(stderr,"%s is empty\n",filename); - close(fd); - return; - } - - mapsize = st.st_size; - mapsize = (mapsize+pagesizem1) & ~pagesizem1; - map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0); - if ((long) map == -1) { - perror("mkdep: mmap"); - close(fd); - return; - } - if ((unsigned long) map % sizeof(unsigned long) != 0) - { - fprintf(stderr, "do_depend: map not aligned\n"); - exit(1); - } - - hasdep = 0; - clear_config(); - state_machine(map, map+st.st_size); - if (hasdep) { - puts(""); - } - - munmap(map, mapsize); - close(fd); -} - - - -/* - * Generate dependencies for all files. - */ -int main(int argc, char **argv) -{ - int len; - const char *hpath; - - hpath = getenv("TOPDIR"); - if (!hpath) { - fputs("mkdep: TOPDIR not set in environment. " - "Don't bypass the top level Makefile.\n", stderr); - return 1; - } - - add_path("."); /* for #include "..." */ - - while (++argv, --argc > 0) { - if (strncmp(*argv, "-I", 2) == 0) { - if (*((*argv)+2)) { - add_path((*argv)+2); - } - else { - ++argv; - --argc; - add_path(*argv); - } - } - else if (strcmp(*argv, "--") == 0) { - break; - } - } - - add_path(hpath); /* must be last entry, for config files */ - - while (--argc > 0) { - const char * filename = *++argv; - g_filename = 0; - len = strlen(filename); - memcpy(depname, filename, len+1); - if (len > 2 && filename[len-2] == '.') { - if (filename[len-1] == 'c' || filename[len-1] == 'S') { - depname[len-1] = 'o'; - g_filename = filename; - } - } - do_depend(filename); - } - if (len_precious) { - *(str_precious+len_precious) = '\0'; - printf(".PRECIOUS:%s\n", str_precious); - } - return 0; -} |