bb_mkdep speed up * 10!
diff --git a/scripts/bb_mkdep.c b/scripts/bb_mkdep.c
index 4083973..68b3f5b 100644
--- a/scripts/bb_mkdep.c
+++ b/scripts/bb_mkdep.c
@@ -50,19 +50,19 @@
 
 /* partial and simplify libbb routine */
 
-void bb_error_d(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
-char * bb_asprint(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
+static void bb_error_d(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
+static char * bb_asprint(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
 
 /* stolen from libbb as is */
 typedef struct llist_s {
 	char *data;
 	struct llist_s *link;
 } llist_t;
-llist_t *llist_add_to(llist_t *old_head, char *new_item);
-void *xrealloc(void *p, size_t size);
-void *xmalloc(size_t size);
-char *bb_xstrdup(const char *s);
-char *bb_simplify_path(const char *path);
+static llist_t *llist_add_to(llist_t *old_head, char *new_item);
+static void *xrealloc(void *p, size_t size);
+static void *xmalloc(size_t size);
+static char *bb_xstrdup(const char *s);
+static char *bb_simplify_path(const char *path);
 
 /* for lexical analyzier */
 static bb_key_t *key_top;
@@ -70,6 +70,8 @@
 static void parse_inc(const char *include, const char *fname);
 static void parse_conf_opt(char *opt, const char *val, size_t rsz);
 
+static char first_char_conf_opts[256];  /* for speed */
+
 #define CHECK_ONLY  0
 #define MAKE_NEW    1
 static bb_key_t *find_already(bb_key_t *k, const char *nk, int flg_save_new);
@@ -112,7 +114,8 @@
   int state;
   int line;
   static size_t mema_id;
-  char *id = xmalloc(mema_id=128);  /* fist allocate */
+  static char *id_s;
+  char *id;
   size_t id_len = 0;                /* stupid initialize */
   char *val = NULL;
   unsigned char *optr, *oend;
@@ -145,6 +148,11 @@
     oend = optr + st.st_size;
   }
 
+  if(id_s == NULL) {
+    /* fist allocate */
+    id_s = xmalloc(mema_id=128);
+  }
+  id = id_s;
   line = 1;
   called = state = S;
 
@@ -220,14 +228,22 @@
 			state = c;
 		} else if(ISALNUM(c)) {
 			/* <S>[A-Z_a-z0-9] */
-			id_len = 0;
-			do {
+
+			/* trick for fast drop id
+			   if key with this first char undefined */
+			if(first_char_conf_opts[c] == 0) {
+			    /* skip <S>[A-Z_a-z0-9]+ */
+			    do getc1(); while(ISALNUM(c));
+			} else {
+			    id_len = 0;
+			    do {
 				/* <S>[A-Z_a-z0-9]+ */
 				put_id(c);
 				getc1();
-			} while(ISALNUM(c));
-			put_id(0);
-			find_already(key_top, id, CHECK_ONLY);
+			    } while(ISALNUM(c));
+			    put_id(0);
+			    find_already(key_top, id, CHECK_ONLY);
+			}
 		} else {
 		    /* <S>. */
 		    prev_state = ANY;
@@ -492,31 +508,32 @@
 		r_cmp = xrealloc(r_cmp, recordsz);
 	    }
 	    s = record_buf;
-	    if(val)
-		sprintf(s, "#define %s%s%s\n", opt, (*val ? " " : ""), val);
-	    else
-		sprintf(s, "#undef %s\n", opt);
 	    /* may be short count " " */
-	    recordsz = strlen(s);
+	    if(val)
+		recordsz = sprintf(s, "#define %s%s%s\n", opt, (*val ? " " : ""), val);
+	    else
+		recordsz = sprintf(s, "#undef %s\n", opt);
+	    first_char_conf_opts[((int)((unsigned char)(*opt)))] = *opt;
 	    /* key converting [A-Z] -> [a-z] */
 	    for(p = opt; *p; p++) {
 		if(*p >= 'A' && *p <= 'Z')
 			*p = *p - 'A' + 'a';
-		if(*p == '_')
-		    *p = '/';
+		else if(*p == '_')
+			*p = '/';
 	    }
 	    p = bb_asprint("%s/%s.h", kp, opt);
 	    cur->stored_path = opt = p;
-	    while(*++p) {
-		/* Auto-create directories. */
-		if (*p == '/') {
-		    *p = '\0';
-		    if (stat(opt, &st) != 0 && mkdir(opt, 0755) != 0)
-			bb_error_d("mkdir(%s): %m", opt);
-		    *p = '/';
+	    if(stat(opt, &st)) {
+		while(*++p) {
+		    /* Auto-create directories. */
+		    if (*p == '/') {
+			*p = '\0';
+			if (stat(opt, &st) != 0 && mkdir(opt, 0755) != 0)
+			    bb_error_d("mkdir(%s): %m", opt);
+			*p = '/';
+		    }
 		}
-	    }
-	    if(stat(opt, &st) == 0) {
+	    } else {
 		    /* found */
 		    if(st.st_size == recordsz) {
 			fd = open(opt, O_RDONLY);
@@ -594,11 +611,11 @@
 
 static llist_t *filter_chd(const char *fe, const char *p, llist_t *pdirs)
 {
-    const char *e;
     struct stat st;
     char *fp;
     char *afp;
     llist_t *cfl;
+    static struct stat st_kp;
 
     if (*fe == '.')
 	return NULL;
@@ -608,40 +625,45 @@
 	free(fp);
 	return NULL;
     }
-    afp = bb_simplify_path(fp);
-    if(S_ISDIR(st.st_mode)) {
-	if(strcmp(kp, afp) == 0) {
-	    /* is autogenerated to kp/key* by previous usage */
-	    free(afp);
+    if(S_ISREG(st.st_mode)) {
+	const char *e = strrchr(fe, '.');
+
+	if(e == NULL || !((e[1]=='c' || e[1]=='h') && e[2]=='\0')) {
+	    /* direntry is regular file, but is not *.[ch] */
 	    free(fp);
-	    /* drop scan kp/ directory */
 	    return NULL;
 	}
-	free(afp);
-	return llist_add_to(pdirs, fp);
-    }
-    if(!S_ISREG(st.st_mode)) {
+    } else {
+	if(st_kp.st_ino == 0) {
+	    /* first call */
+	    if(stat(kp, &st_kp))
+		bb_error_d("stat(%s): %m", kp);
+	    if(!S_ISDIR(st_kp.st_mode))
+		bb_error_d("%s is not directory", kp);
+	}
+	if(S_ISDIR(st.st_mode)) {
+	    if (st.st_dev == st_kp.st_dev && st.st_ino == st_kp.st_ino) {
+		/* is autogenerated to kp/key* by previous usage */
+		free(fp);
+		/* drop scan kp/ directory */
+		return NULL;
+	    }
+	    return llist_add_to(pdirs, fp);
+	}
 	/* hmm, is device! */
-	free(afp);
 	free(fp);
 	return NULL;
     }
-    e = strrchr(fe, '.');
-    if(e == NULL || !((e[1]=='c' || e[1]=='h') && e[2]=='\0')) {
-	/* direntry is not directory or *.[ch] */
-	free(afp);
-	free(fp);
-	return NULL;
-    }
+    afp = bb_simplify_path(fp);
     for(cfl = configs; cfl; cfl = cfl->link) {
 	if(cfl->data && strcmp(cfl->data, afp) == 0) {
-	    /* parse configs.h */
-	    free(afp);
-	    c_lex(fp, 1);
-	    free(fp);
-	    free(cfl->data);
-	    cfl->data = NULL;
-	    return NULL;
+		/* parse configs.h */
+		free(afp);
+		c_lex(fp, 1);
+		free(fp);
+		free(cfl->data);
+		cfl->data = NULL;
+		return NULL;
 	}
     }
     free(fp);
@@ -680,6 +702,13 @@
 	}
 	dirs = d_add;
     }
+    for(d = configs; d; d = d->link) {
+	if(d->data) {
+	    /* configs.h placed outsize of "." */
+	    c_lex(d->data, 1);
+	    free(d->data);
+	}
+    }
 }
 
 int main(int argc, char **argv)
@@ -725,8 +754,8 @@
 	    s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH);
 	    configs = llist_add_to(configs, s);
 	}
-	scan_dir_find_ch_files(".");
 
+	scan_dir_find_ch_files(".");
 	for(fl = files; fl; fl = fl->link) {
 		c_lex(fl->data, 0);
 		if(generate_dep) {
@@ -739,7 +768,7 @@
 	return 0;
 }
 
-void bb_error_d(const char *s, ...)
+static void bb_error_d(const char *s, ...)
 {
 	va_list p;
 
@@ -751,7 +780,7 @@
 }
 
 
-void *xmalloc(size_t size)
+static void *xmalloc(size_t size)
 {
 	void *p = malloc(size);
 
@@ -760,14 +789,14 @@
 	return p;
 }
 
-void *xrealloc(void *p, size_t size) {
+static void *xrealloc(void *p, size_t size) {
 	p = realloc(p, size);
 	if(p == NULL)
 		bb_error_d("memory exhausted");
 	return p;
 }
 
-char *bb_asprint(const char *format, ...)
+static char *bb_asprint(const char *format, ...)
 {
 	va_list p;
 	int r;
@@ -782,7 +811,7 @@
 	return out;
 }
 
-llist_t *llist_add_to(llist_t *old_head, char *new_item)
+static llist_t *llist_add_to(llist_t *old_head, char *new_item)
 {
 	llist_t *new_head;
 
@@ -793,15 +822,16 @@
 	return(new_head);
 }
 
-char *bb_xstrdup(const char *s)
+static char *bb_xstrdup(const char *s)
 {
-    char *r = strdup(s);
-    if(r == NULL)
-	bb_error_d("memory exhausted");
-    return r;
+	char *r = strdup(s);
+
+	if(r == NULL)
+	    bb_error_d("memory exhausted");
+	return r;
 }
 
-char *bb_simplify_path(const char *path)
+static char *bb_simplify_path(const char *path)
 {
 	char *s, *start, *p;
 
@@ -828,26 +858,26 @@
 	p = s = start;
 
 	do {
-		if (*p == '/') {
-			if (*s == '/') {        /* skip duplicate (or initial) slash */
-				continue;
-			} else if (*s == '.') {
-				if (s[1] == '/' || s[1] == 0) { /* remove extra '.' */
-					continue;
-				} else if ((s[1] == '.') && (s[2] == '/' || s[2] == 0)) {
-					++s;
-					if (p > start) {
-						while (*--p != '/');    /* omit previous dir */
-					}
-					continue;
-				}
+	    if (*p == '/') {
+		if (*s == '/') {    /* skip duplicate (or initial) slash */
+		    continue;
+		} else if (*s == '.') {
+		    if (s[1] == '/' || s[1] == 0) { /* remove extra '.' */
+			continue;
+		    } else if ((s[1] == '.') && (s[2] == '/' || s[2] == 0)) {
+			++s;
+			if (p > start) {
+			    while (*--p != '/');    /* omit previous dir */
 			}
+			continue;
+		    }
 		}
-		*++p = *s;
+	    }
+	    *++p = *s;
 	} while (*++s);
 
-	if ((p == start) || (*p != '/')) {      /* not a trailing slash */
-		++p;                            /* so keep last character */
+	if ((p == start) || (*p != '/')) {  /* not a trailing slash */
+	    ++p;                            /* so keep last character */
 	}
 	*p = 0;