bb_mkdep speed up * 10!
author"Vladimir N. Oleynik" <dzo@simtreas.ru>
Mon, 12 Sep 2005 16:39:47 +0000 (16:39 -0000)
committer"Vladimir N. Oleynik" <dzo@simtreas.ru>
Mon, 12 Sep 2005 16:39:47 +0000 (16:39 -0000)
scripts/bb_mkdep.c

index 408397332e1c84d08edfb5adb52c4ec2b0f8f754..68b3f5bce2cd7165e1417e4e4c74c99828a8057a 100644 (file)
@@ -50,19 +50,19 @@ typedef struct BB_KEYS {
 
 /* 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 bb_key_t *key_top;
 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 @@ static void c_lex(const char *fname, int flg_config_include)
   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 @@ static void c_lex(const char *fname, int flg_config_include)
     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 @@ static void c_lex(const char *fname, int flg_config_include)
                        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 @@ static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
                r_cmp = xrealloc(r_cmp, recordsz);
            }
            s = record_buf;
+           /* may be short count " " */
            if(val)
-               sprintf(s, "#define %s%s%s\n", opt, (*val ? " " : ""), val);
+               recordsz = sprintf(s, "#define %s%s%s\n", opt, (*val ? " " : ""), val);
            else
-               sprintf(s, "#undef %s\n", opt);
-           /* may be short count " " */
-           recordsz = strlen(s);
+               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 *files;
 
 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 @@ static llist_t *filter_chd(const char *fe, const char *p, llist_t *pdirs)
        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 @@ static void scan_dir_find_ch_files(char *p)
        }
        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 @@ int main(int argc, char **argv)
            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 @@ int main(int argc, char **argv)
        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 bb_error_d(const char *s, ...)
 }
 
 
-void *xmalloc(size_t size)
+static void *xmalloc(size_t size)
 {
        void *p = malloc(size);
 
@@ -760,14 +789,14 @@ void *xmalloc(size_t size)
        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 @@ char *bb_asprint(const char *format, ...)
        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 @@ llist_t *llist_add_to(llist_t *old_head, char *new_item)
        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 @@ char *bb_simplify_path(const char *path)
        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;