bb_mkdep speed up * 10!
This commit was genuinely broken at the time (not related to our build system): scripts/config/mkconfigs.c (2005-08-01 - 2006-10-05 arasi) uretilen bbconfigopts.h icine .config satirlarini kacissiz, ham newline'larla gömüyordu - gecerli C degildi, busybox'un kendi bb_mkdep araci bile parse edemiyordu (7d219aab7 ile duzeltildi, mkconfigs shell scripte cevrildi)
No binary (build failed)
—
(log yok)
| @@ -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; | |