diff options
Diffstat (limited to 'scripts/bb_mkdep.c')
-rw-r--r-- | scripts/bb_mkdep.c | 811 |
1 files changed, 415 insertions, 396 deletions
diff --git a/scripts/bb_mkdep.c b/scripts/bb_mkdep.c index 76db960fd..758b78cb9 100644 --- a/scripts/bb_mkdep.c +++ b/scripts/bb_mkdep.c @@ -1,9 +1,20 @@ /* - * Another fast dependencies generator for Makefiles, Version 2.5 + * Another fast dependencies generator for Makefiles, Version 3.0 * * Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru> + * * mmaping file may be originally by Linus Torvalds. * + * bb_simplify_path() + * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org> + * + * xmalloc() bb_xstrdup() bb_error_d(): + * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> + * + * llist routine + * Copyright (C) 2003 Glenn McGrath + * Copyright (C) Vladimir Oleynik <dzo@simtreas.ru> + * * (c) 2005 Bernhard Fischer: * - commentary typos, * - move "memory exhausted" into msg_enomem, @@ -11,14 +22,13 @@ * * This program does: * 1) find #define KEY VALUE or #undef KEY from include/config.h - * 2) save include/config/key*.h if changed after previous usage - * 3) recursive find and scan *.[ch] files, but skips scan of include/config/ - * 4) find #include "*.h" and KEYs using, if not as #define and #undef - * 5) generate dependencies to stdout + * 2) recursive find and scan *.[ch] files, but skips scan of include/config/ + * 3) find #include "*.h" and KEYs using, if not as #define and #undef + * 4) generate dependencies to stdout * pwd/file.o: include/config/key*.h found_include_*.h * path/inc.h: include/config/key*.h found_included_include_*.h + * 5) save include/config/key*.h if changed after previous usage * This program does not generate dependencies for #include <...> - * BUG: all includes name must unique */ #define LOCAL_INCLUDE_PATH "include" @@ -51,62 +61,100 @@ #include <unistd.h> #include <errno.h> #include <fcntl.h> +#include <limits.h> -typedef struct BB_KEYS { - char *keyname; - size_t key_sz; - const char *value; - char *stored_path; - char *checked; - struct BB_KEYS *next; -} bb_key_t; - -static bb_key_t *check_key(bb_key_t *k, const char *nk, size_t key_sz); -static bb_key_t *make_new_key(bb_key_t *k, const char *nk, size_t key_sz); - /* partial and simplified libbb routine */ 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))); +static char *bb_simplify_path(const char *path); /* stolen from libbb as is */ typedef struct llist_s { char *data; struct llist_s *link; } llist_t; -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); -/* error messages */ + static const char msg_enomem[] = "memory exhausted"; -/* for lexical analyser */ -static bb_key_t *key_top; -static llist_t *configs; +/* inline realization for fast works */ +static inline void *xmalloc(size_t size) +{ + void *p = malloc(size); -static int mode; -#define CONFIG_MODE 0 -#define SOURCES_MODE 1 + if(p == NULL) + bb_error_d(msg_enomem); + return p; +} + +static inline char *bb_xstrdup(const char *s) +{ + char *r = strdup(s); -static void parse_inc(const char *include, const char *fname, size_t key_sz); -static void parse_conf_opt(const char *opt, const char *val, - size_t rsz, size_t key_sz); + if(r == NULL) + bb_error_d(msg_enomem); + return r; +} + + +static int dontgenerate_dep; /* flag -d usaged */ +static int noiwarning; /* flag -w usaged */ +static llist_t *configs; /* list of -c usaged and them stat() after parsed */ +static llist_t *Iop; /* list of -I include usaged */ + +static char *pwd; /* current work directory */ +static size_t replace; /* replace current work derectory to build dir */ + +static const char *kp; /* KEY path, argument of -k usaged */ +static size_t kp_len; +static struct stat st_kp; /* stat(kp) */ + +typedef struct BB_KEYS { + char *keyname; + size_t key_sz; + const char *value; + const char *checked; + char *stored_path; + const char *src_have_this_key; + struct BB_KEYS *next; +} bb_key_t; + +static bb_key_t *key_top; /* list of found KEYs */ +static bb_key_t *Ifound; /* list of parsed includes */ + + +static void parse_conf_opt(const char *opt, const char *val, size_t key_sz); +static void parse_inc(const char *include, const char *fname); + +static inline bb_key_t *check_key(bb_key_t *k, const char *nk, size_t key_sz) +{ + bb_key_t *cur; + + for(cur = k; cur; cur = cur->next) { + if(key_sz == cur->key_sz && memcmp(cur->keyname, nk, key_sz) == 0) { + cur->checked = cur->stored_path; + return cur; + } + } + return NULL; +} + +/* for lexical analyser */ +static int pagesizem1; /* padding mask = getpagesize() - 1 */ /* for speed tricks */ -static char first_chars[257]; /* + L_EOF */ -static char isalnums[257]; /* + L_EOF */ +static char first_chars[1+UCHAR_MAX]; /* + L_EOF */ +static char isalnums[1+UCHAR_MAX]; /* + L_EOF */ /* trick for fast find "define", "include", "undef" */ -static char first_chars_diu[256] = { - [(int)'d'] = (char)5, /* strlen("define") - 1; */ +static const char first_chars_diu[UCHAR_MAX] = { + [(int)'d'] = (char)5, /* strlen("define") - 1; */ [(int)'i'] = (char)6, /* strlen("include") - 1; */ - [(int)'u'] = (char)4, /* strlen("undef") - 1; */ + [(int)'u'] = (char)4, /* strlen("undef") - 1; */ }; -static int pagesizem1; -static size_t mema_id = 128; /* first allocated for id */ -static char *id_s; - +#define CONFIG_MODE 0 +#define SOURCES_MODE 1 +static int mode; #define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s) @@ -117,44 +165,40 @@ static char *id_s; #define REM '/' /* block comment */ #define BS '\\' /* back slash */ #define POUND '#' /* # */ -#define I 'i' /* #include preprocessor's directive */ -#define D 'd' /* #define preprocessor's directive */ -#define U 'u' /* #undef preprocessor's directive */ -#define LI 'I' /* #include "... */ +#define D '5' /* #define preprocessor's directive */ +#define I '6' /* #include preprocessor's directive */ +#define U '4' /* #undef preprocessor's directive */ #define DK 'K' /* #define KEY... (config mode) */ -#define DV 'V' /* #define KEY "VALUE or #define KEY 'VALUE */ -#define NLC 'n' /* \ and \n */ #define ANY '*' /* any unparsed chars */ -#define L_EOF 256 /* [A-Z_a-z] */ #define ID(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') /* [A-Z_a-z0-9] */ #define ISALNUM(c) (ID(c) || (c >= '0' && c <= '9')) -#define getc1() do { c = (optr >= oend) ? L_EOF : *optr++; } while(0) -#define ungetc1() optr-- +#define L_EOF (1+UCHAR_MAX) -#define put_id(c) do { if(id_len == local_mema_id) \ - id = xrealloc(id, local_mema_id += 16); \ - id[id_len++] = c; } while(0) +#define getc0() do { c = (optr >= oend) ? L_EOF : *optr++; } while(0) + +#define getc1() do { getc0(); if(c == BS) { getc0(); \ + if(c == '\n') { line++; continue; } \ + else { optr--; c = BS; } \ + } break; } while(1) + +static char id_s[4096]; +#define put_id(ic) do { if(id_len == sizeof(id_s)) goto too_long; \ + id[id_len++] = ic; } while(0) /* stupid C lexical analyser */ static void c_lex(const char *fname, long fsize) { - int c = L_EOF; /* stupid initialize */ - int prev_state = L_EOF; - int called; + int c; int state; int line; char *id = id_s; - size_t local_mema_id = mema_id; size_t id_len = 0; /* stupid initialize */ - char *val = NULL; unsigned char *optr, *oend; - unsigned char *start = NULL; /* stupid initialize */ - size_t opt_len = 0; /* stupid initialize */ int fd; char *map; @@ -178,30 +222,15 @@ static void c_lex(const char *fname, long fsize) oend = optr + fsize; line = 1; - called = state = S; + state = S; for(;;) { - if(prev_state != state) { - prev_state = state; - getc1(); - } - + getc1(); + for(;;) { /* [ \t]+ eat first space */ while(c == ' ' || c == '\t') getc1(); - if(c == BS) { - getc1(); - if(c == '\n') { - /* \\\n eat continued */ - line++; - prev_state = NLC; - continue; - } - ungetc1(); - c = BS; - } - if(state == S) { while(first_chars[c] == ANY) { /* <S>unparsed */ @@ -211,33 +240,44 @@ static void c_lex(const char *fname, long fsize) } if(c == L_EOF) { /* <S><<EOF>> */ - id_s = id; - mema_id = local_mema_id; munmap(map, mapsize); close(fd); return; } if(c == REM) { /* <S>/ */ - getc1(); /* eat <S>/ */ + getc0(); if(c == REM) { /* <S>"//"[^\n]* */ - do getc1(); while(c != '\n' && c != L_EOF); + do getc0(); while(c != '\n' && c != L_EOF); } else if(c == '*') { - /* <S>[/][*] */ - called = S; - state = REM; + /* <S>[/][*] goto parse block comments */ + break; } } else if(c == POUND) { /* <S># */ - start = optr - 1; state = c; + getc1(); } else if(c == STR || c == CHR) { /* <S>\"|\' */ - val = NULL; - called = S; - state = c; - } else if(c != BS) { + int qc = c; + + for(;;) { + /* <STR,CHR>. */ + getc1(); + if(c == qc) { + /* <STR>\" or <CHR>\' */ + break; + } + if(c == BS) { + /* <STR,CHR>\\ but is not <STR,CHR>\\\n */ + getc0(); + } + if(c == '\n' || c == L_EOF) + yy_error_d("unterminated"); + } + getc1(); + } else { /* <S>[A-Z_a-z0-9] */ /* trick for fast drop id @@ -254,90 +294,20 @@ static void c_lex(const char *fname, long fsize) } while(isalnums[c]); check_key(key_top, id, id_len); } - } else { - /* <S>\\ */ - prev_state = c; } continue; } - if(state == REM) { - for(;;) { - /* <REM>[^*]+ */ - while(c != '*') { - if(c == '\n') { - /* <REM>\n */ - if(called != S) - yy_error_d("unexpected newline"); - line++; - } else if(c == L_EOF) - yy_error_d("unexpected EOF"); - getc1(); - } - /* <REM>[*] */ - getc1(); - if(c == REM) { - /* <REM>[*][/] */ - state = called; - break; - } - } - continue; - } - if(state == STR || state == CHR) { - for(;;) { - /* <STR,CHR>\n|<<EOF>> */ - if(c == '\n' || c == L_EOF) - yy_error_d("unterminated"); - if(c == BS) { - /* <STR,CHR>\\ */ - getc1(); - if(c != BS && c != '\n' && c != state) { - /* another usage \ in str or char */ - if(c == L_EOF) - yy_error_d("unexpected EOF"); - if(val) - put_id(c); - continue; - } - /* <STR,CHR>\\[\\\n] or <STR>\\\" or <CHR>\\\' */ - /* eat 2 char */ - if(c == '\n') - line++; - else if(val) - put_id(c); - } else if(c == state) { - /* <STR>\" or <CHR>\' */ - if(called == LI) { - /* store "include.h" */ - parse_inc(id, fname, id_len); - } else if(called == DV) { - put_id(c); /* config mode #define KEY "VAL"<- */ - put_id(0); - parse_conf_opt(id, val, (optr - start), opt_len); - } - state = S; - break; - } else if(val) - put_id(c); - /* <STR,CHR>. */ - getc1(); - } - continue; - } - /* begin preprocessor states */ if(c == L_EOF) yy_error_d("unexpected EOF"); if(c == REM) { /* <#.*>/ */ - getc1(); + getc0(); if(c == REM) yy_error_d("detected // in preprocessor line"); if(c == '*') { - /* <#.*>[/][*] */ - called = state; - state = REM; - continue; + /* <#.*>[/][*] goto parse block comments */ + break; } /* hmm, #.*[/] */ yy_error_d("strange preprocessor line"); @@ -345,43 +315,49 @@ static void c_lex(const char *fname, long fsize) if(state == POUND) { /* tricks */ static const char * const preproc[] = { - /* 0-3 */ - "", "", "", "", - /* 4 */ /* 5 */ /* 6 */ - "ndef", "efine", "nclude", + /* 0 1 2 3 4 5 6 */ + "", "", "", "", "ndef", "efine", "nclude" }; size_t diu = first_chars_diu[c]; /* strlen and preproc ptr */ - const unsigned char *p = optr; - while(isalnums[c]) getc1(); - /* have str begined with c, readed == strlen key and compared */ - if(diu != S && diu == (optr-p-1) && !memcmp(p, preproc[diu], diu)) { - state = p[-1]; - id_len = 0; /* common for save */ + state = S; + if(diu != S) { + getc1(); + id_len = 0; + while(isalnums[c]) { + put_id(c); + getc1(); + } + /* have str begined with c, readed == strlen key and compared */ + if(diu == id_len && !memcmp(id, preproc[diu], diu)) { + state = diu + '0'; + id_len = 0; /* common for save */ + } } else { - state = S; + while(isalnums[c]) getc1(); } - ungetc1(); - continue; - } - if(state == I) { + } else if(state == I) { if(c == STR) { /* <I>\" */ - val = id; - called = LI; - state = STR; - } else { - /* another (may be wrong) #include ... */ - ungetc1(); - state = S; + for(;;) { + getc1(); + if(c == STR) + break; + if(c == L_EOF) + yy_error_d("unexpected EOF"); + put_id(c); + } + put_id(0); + /* store "include.h" */ + parse_inc(id, fname); + getc1(); } - continue; - } - if(state == D || state == U) { + /* else another (may be wrong) #include ... */ + state = S; + } else if(state == D || state == U) { if(mode == SOURCES_MODE) { /* ignore depend with #define or #undef KEY */ - while(isalnums[c]) - getc1(); + while(isalnums[c]) getc1(); state = S; } else { /* save KEY from #"define"|"undef" ... */ @@ -392,145 +368,164 @@ static void c_lex(const char *fname, long fsize) if(!id_len) yy_error_d("expected identifier"); if(state == U) { - parse_conf_opt(id, NULL, (optr - start), id_len); + parse_conf_opt(id, NULL, id_len); state = S; } else { /* D -> DK */ - opt_len = id_len; + if(c == '(') + yy_error_d("unexpected function macro"); state = DK; } } - ungetc1(); - continue; - } - if(state == DK) { - /* #define KEY[ ] (config mode) */ - val = id + id_len; - if(c == STR || c == CHR) { - /* define KEY "... or define KEY '... */ - put_id(c); - called = DV; - state = c; - continue; - } - while(isalnums[c]) { - /* VALUE */ + } else { + /* state==<DK> #define KEY[ ] (config mode) */ + size_t opt_len = id_len; + char *val = id + opt_len; + char *sp; + + for(;;) { + if(c == L_EOF || c == '\n') + break; put_id(c); getc1(); } + sp = id + id_len; put_id(0); - parse_conf_opt(id, val, (optr - start), opt_len); + /* trim tail spaces */ + while(--sp >= val && (*sp == ' ' || *sp == '\t' + || *sp == '\f' || *sp == '\v')) + *sp = '\0'; + parse_conf_opt(id, val, opt_len); state = S; - ungetc1(); - continue; } } + + /* <REM> */ + getc0(); + for(;;) { + /* <REM>[^*]+ */ + while(c != '*') { + if(c == '\n') { + /* <REM>\n */ + if(state != S) + yy_error_d("unexpected newline"); + line++; + } else if(c == L_EOF) + yy_error_d("unexpected EOF"); + getc0(); + } + /* <REM>[*] */ + getc0(); + if(c == REM) { + /* <REM>[*][/] */ + break; + } + } + } +too_long: + yy_error_d("phrase too long"); } -static void show_usage(void) __attribute__ ((noreturn)); -static void show_usage(void) +/* bb_simplify_path special variant for apsolute pathname */ +static size_t bb_qa_simplify_path(char *path) { - bb_error_d("%s\n%s\n", bb_mkdep_terse_options, bb_mkdep_full_options); -} + char *s, *p; -static const char *kp; -static size_t kp_len; -static llist_t *Iop; -static bb_key_t *Ifound; -static int noiwarning; + p = s = path; -static bb_key_t *check_key(bb_key_t *k, const char *nk, size_t key_sz) -{ - bb_key_t *cur; + 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 > path) { + while (*--p != '/'); /* omit previous dir */ + } + continue; + } + } + } + *++p = *s; + } while (*++s); - for(cur = k; cur; cur = cur->next) { - if(key_sz == cur->key_sz && memcmp(cur->keyname, nk, key_sz) == 0) { - cur->checked = cur->stored_path; - return cur; + if ((p == path) || (*p != '/')) { /* not a trailing slash */ + ++p; /* so keep last character */ } - } - return NULL; -} - -static bb_key_t *make_new_key(bb_key_t *k, const char *nk, size_t key_sz) -{ - bb_key_t *cur; + *p = 0; - cur = xmalloc(sizeof(bb_key_t) + key_sz + 1); - cur->keyname = memcpy(cur + 1, nk, key_sz); - cur->keyname[key_sz] = '\0'; - cur->key_sz = key_sz; - cur->checked = NULL; - cur->next = k; - return cur; + return (p - path); } -static inline char *store_include_fullpath(char *p_i, bb_key_t *li) +static void parse_inc(const char *include, const char *fname) { - char *ok; - - if(access(p_i, F_OK) == 0) { - ok = li->stored_path = bb_simplify_path(p_i); - li->checked = ok; + bb_key_t *cur; + const char *p_i; + llist_t *lo; + char *ap; + size_t key_sz; + + if(*include == '/') { + lo = NULL; + ap = bb_xstrdup(include); } else { - ok = NULL; + int w; + const char *p; + + lo = Iop; + p = strrchr(fname, '/'); /* fname have absolute pathname */ + w = (p-fname); + /* find from current directory of source file */ + ap = bb_asprint("%.*s/%s", w, fname, include); } - free(p_i); - return ok; -} - -static void parse_inc(const char *include, const char *fname, size_t key_sz) -{ - bb_key_t *li; - char *p_i; - llist_t *lo; - li = check_key(Ifound, include, key_sz); - if(li) + for(;;) { + key_sz = bb_qa_simplify_path(ap); + cur = check_key(Ifound, ap, key_sz); + if(cur) { + cur->checked = cur->value; + free(ap); return; - Ifound = li = make_new_key(Ifound, include, key_sz); - include = li->keyname; - if(include[0] != '/') { - /* relative */ - int w; - - p_i = strrchr(fname, '/'); /* fname have absolute pathname */ - w = (p_i-fname); - /* find from current directory of source file */ - p_i = bb_asprint("%.*s/%s", w, fname, include); - if(store_include_fullpath(p_i, li)) - return; - /* find from "-I include" specified directories */ - for(lo = Iop; lo; lo = lo->link) { - p_i = bb_asprint("%s/%s", lo->data, include); - if(store_include_fullpath(p_i, li)) - return; - } - } else { - /* absolute include pathname */ - if(access(include, F_OK) == 0) { - li->checked = li->stored_path = bb_xstrdup(include); - return; - } } - li->stored_path = NULL; - if(noiwarning) - fprintf(stderr, "%s: Warning: #include \"%s\" not found in specified paths\n", fname, include); + if(access(ap, F_OK) == 0) { + /* found */ + p_i = ap; + break; + } else if(lo == NULL) { + p_i = NULL; + break; + } + + /* find from "-I include" specified directories */ + free(ap); + /* lo->data have absolute pathname */ + ap = bb_asprint("%s/%s", lo->data, include); + lo = lo->link; + } + + cur = xmalloc(sizeof(bb_key_t)); + cur->keyname = ap; + cur->key_sz = key_sz; + cur->stored_path = ap; + cur->value = cur->checked = p_i; + if(p_i == NULL && noiwarning) + fprintf(stderr, "%s: Warning: #include \"%s\" not found\n", fname, include); + cur->next = Ifound; + Ifound = cur; } -static void parse_conf_opt(const char *opt, const char *val, - size_t recordsz, size_t key_sz) +static size_t max_rec_sz; + +static void parse_conf_opt(const char *opt, const char *val, size_t key_sz) { bb_key_t *cur; char *k; - char *s, *p; - struct stat st; - int fd; - int cmp_ok = 0; - static char *record_buf; - static size_t r_sz; - ssize_t rw_ret; + char *p; + size_t val_sz = 0; cur = check_key(key_top, opt, key_sz); if(cur != NULL) { @@ -543,29 +538,33 @@ static void parse_conf_opt(const char *opt, const char *val, k = cur->keyname; fprintf(stderr, "Warning: redefined %s\n", k); } else { - key_top = cur = make_new_key(key_top, opt, key_sz); - k = cur->keyname; + size_t recordsz; + + if(val && *val) + val_sz = strlen(val) + 1; + recordsz = key_sz + val_sz + 1; + if(max_rec_sz < recordsz) + max_rec_sz = recordsz; + cur = xmalloc(sizeof(bb_key_t) + recordsz); + k = cur->keyname = memcpy(cur + 1, opt, key_sz); + cur->keyname[key_sz] = '\0'; + cur->key_sz = key_sz; + cur->checked = NULL; + cur->src_have_this_key = NULL; + cur->next = key_top; + key_top = cur; } - /* do generate record */ - recordsz += 2; /* \n\0 */ - if(recordsz > r_sz) - record_buf = xrealloc(record_buf, (r_sz = recordsz) * 2); - s = record_buf; - /* may be short count " " */ + /* save VAL */ if(val) { if(*val == '\0') { cur->value = ""; - recordsz = sprintf(s, "#define %s\n", k); } else { - cur->value = bb_xstrdup(val); - recordsz = sprintf(s, "#define %s %s\n", k, val); + cur->value = p = cur->keyname + key_sz + 1; + memcpy(p, val, val_sz); } } else { cur->value = NULL; - recordsz = sprintf(s, "#undef %s\n", k); } - /* size_t -> ssize_t :( */ - rw_ret = (ssize_t)recordsz; /* trick, save first char KEY for do fast identify id */ first_chars[(int)*k] = *k; @@ -577,80 +576,118 @@ static void parse_conf_opt(const char *opt, const char *val, else if(*p == '_' && p[1] > '9') /* do not change A_1 to A/1 */ *p = '/'; } - /* check kp/key.h if present after previous usage */ - if(stat(k, &st)) { - for(p = k + kp_len + 1; *p; p++) { - /* Auto-create directories. */ - if (*p == '/') { - *p = '\0'; - if (access(k, F_OK) != 0 && mkdir(k, 0755) != 0) - bb_error_d("mkdir(%s): %m", k); - *p = '/'; +} + +static void store_keys(void) +{ + bb_key_t *cur; + char *k; + struct stat st; + int cmp_ok; + ssize_t rw_ret; + size_t recordsz = max_rec_sz * 2 + 10 * 2 + 16; + /* buffer for double "#define KEY VAL\n" */ + char *record_buf = xmalloc(recordsz); + + for(cur = key_top; cur; cur = cur->next) { + if(cur->src_have_this_key) { + /* do generate record */ + k = cur->keyname; + if(cur->value == NULL) { + recordsz = sprintf(record_buf, "#undef %s\n", k); + } else { + const char *val = cur->value; + if(*val == '\0') { + recordsz = sprintf(record_buf, "#define %s\n", k); + } else { + recordsz = sprintf(record_buf, "#define %s %s\n", k, val); } } - } else { - /* found */ - if(st.st_size == (off_t)recordsz) { - char *r_cmp = s + recordsz; - - fd = open(k, O_RDONLY); - if(fd < 0 || read(fd, r_cmp, recordsz) < rw_ret) - bb_error_d("%s: %m", k); - close(fd); - cmp_ok = memcmp(s, r_cmp, recordsz) == 0; + /* size_t -> ssize_t :( */ + rw_ret = (ssize_t)recordsz; + /* check kp/key.h, compare after previous usage */ + cmp_ok = 0; + k = cur->stored_path; + if(stat(k, &st)) { + char *p; + for(p = k + kp_len + 1; *p; p++) { + /* Auto-create directories. */ + if (*p == '/') { + *p = '\0'; + if (access(k, F_OK) != 0 && mkdir(k, 0755) != 0) + bb_error_d("mkdir(%s): %m", k); + *p = '/'; + } } + } else { + /* found */ + if(st.st_size == (off_t)recordsz) { + char *r_cmp; + int fd; + size_t padded = recordsz; + + /* 16-byte padding for read(2) and memcmp(3) */ + padded = (padded+15) & ~15; + r_cmp = record_buf + padded; + fd = open(k, O_RDONLY); + if(fd < 0 || read(fd, r_cmp, recordsz) < rw_ret) + bb_error_d("%s: %m", k); + close(fd); + cmp_ok = memcmp(record_buf, r_cmp, recordsz) == 0; + } + } + if(!cmp_ok) { + int fd = open(k, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if(fd < 0 || write(fd, record_buf, recordsz) < rw_ret) + bb_error_d("%s: %m", k); + close(fd); + } } - if(!cmp_ok) { - fd = open(k, O_WRONLY|O_CREAT|O_TRUNC, 0644); - if(fd < 0 || write(fd, s, recordsz) < rw_ret) - bb_error_d("%s: %m", k); - close(fd); - } + } } -static char *pwd; - static int show_dep(int first, bb_key_t *k, const char *name, const char *f) { bb_key_t *cur; for(cur = k; cur; cur = cur->next) { if(cur->checked) { - if(first) { - if(f == NULL) + if(first >= 0) { + if(first) { + if(f == NULL) printf("\n%s:", name); - else + else printf("\n%s/%s:", pwd, name); - first = 0; - } else { - printf(" \\\n "); + first = 0; + } else { + printf(" \\\n "); + } + printf(" %s", cur->checked); } - printf(" %s", cur->checked); + cur->src_have_this_key = cur->checked; + cur->checked = NULL; } - cur->checked = NULL; } return first; } -static size_t replace; - -static struct stat st_kp; -static int dontgenerate_dep; - static char * parse_chd(const char *fe, const char *p, size_t dirlen) { struct stat st; char *fp; size_t df_sz; - static char *dir_and_entry; - static size_t dir_and_entry_sz; + static char dir_and_entry[4096]; + size_t fe_sz = strlen(fe) + 1; - df_sz = dirlen + strlen(fe) + 2; /* dir/file\0 */ - if(df_sz > dir_and_entry_sz) - dir_and_entry = xrealloc(dir_and_entry, dir_and_entry_sz = df_sz); + df_sz = dirlen + fe_sz + 1; /* dir/file\0 */ + if(df_sz > sizeof(dir_and_entry)) + bb_error_d("%s: file name too long", fe); fp = dir_and_entry; - sprintf(fp, "%s/%s", p, fe); + /* sprintf(fp, "%s/%s", p, fe); */ + memcpy(fp, p, dirlen); + fp[dirlen] = '/'; + memcpy(fp + dirlen + 1, fe, fe_sz); if(stat(fp, &st)) { fprintf(stderr, "Warning: stat(%s): %m\n", fp); @@ -673,17 +710,16 @@ parse_chd(const char *fe, const char *p, size_t dirlen) } } /* direntry is *.[ch] regular file and is not configs */ + c_lex(fp, st.st_size); if(!dontgenerate_dep) { int first; - - c_lex(fp, st.st_size); if(*e == 'c') { /* *.c -> *.o */ *e = 'o'; /* /src_dir/path/file.o to path/file.o */ fp += replace; if(*fp == '/') - fp++; + fp++; } else { e = NULL; } @@ -691,15 +727,15 @@ parse_chd(const char *fe, const char *p, size_t dirlen) first = show_dep(first, key_top, fp, e); if(first == 0) putchar('\n'); + } else { + show_dep(-1, key_top, NULL, NULL); } return NULL; } else if(S_ISDIR(st.st_mode)) { if (st.st_dev == st_kp.st_dev && st.st_ino == st_kp.st_ino) return NULL; /* drop scan kp/ directory */ - /* direntry is directory. buff is returned, begin of zero allocate */ - dir_and_entry = NULL; - dir_and_entry_sz = 0; - return fp; + /* direntry is directory. buff is returned */ + return bb_xstrdup(fp); } /* hmm, direntry is device! */ return NULL; @@ -755,6 +791,11 @@ static void scan_dir_find_ch_files(const char *p) } } +static void show_usage(void) __attribute__ ((noreturn)); +static void show_usage(void) +{ + bb_error_d("%s\n%s\n", bb_mkdep_terse_options, bb_mkdep_full_options); +} int main(int argc, char **argv) { @@ -763,24 +804,25 @@ int main(int argc, char **argv) llist_t *fl; { - /* for bb_simplify_path */ - /* libbb xgetcwd(), this program have not chdir() */ + /* for bb_simplify_path, this program have not chdir() */ + /* libbb-like my xgetcwd() */ unsigned path_max = 512; s = xmalloc (path_max); -#define PATH_INCR 32 while (getcwd (s, path_max) == NULL) { if(errno != ERANGE) bb_error_d("getcwd: %m"); - s = xrealloc (s, path_max += PATH_INCR); - } + free(s); + s = xmalloc(path_max *= 2); + } pwd = s; } while ((i = getopt(argc, argv, "I:c:dk:w")) > 0) { switch(i) { case 'I': - Iop = llist_add_to(Iop, optarg); + s = bb_simplify_path(optarg); + Iop = llist_add_to(Iop, s); break; case 'c': s = bb_simplify_path(optarg); @@ -812,19 +854,18 @@ int main(int argc, char **argv) bb_error_d("%s is not directory", kp); /* defaults */ if(Iop == NULL) - Iop = llist_add_to(Iop, LOCAL_INCLUDE_PATH); + Iop = llist_add_to(Iop, bb_simplify_path(LOCAL_INCLUDE_PATH)); if(configs == NULL) { s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH); configs = llist_add_to(configs, s); } /* for c_lex */ pagesizem1 = getpagesize() - 1; - id_s = xmalloc(mema_id); - for(i = 0; i < 256; i++) { + for(i = 0; i < UCHAR_MAX; i++) { if(ISALNUM(i)) isalnums[i] = i; /* set unparsed chars for speed up of parser */ - else if(i != CHR && i != STR && i != POUND && i != REM && i != BS) + else if(i != CHR && i != STR && i != POUND && i != REM) first_chars[i] = ANY; } first_chars[i] = '-'; /* L_EOF */ @@ -836,8 +877,9 @@ int main(int argc, char **argv) if(stat(fl->data, &st)) bb_error_d("stat(%s): %m", fl->data); c_lex(fl->data, st.st_size); + free(fl->data); /* trick for fast comparing found files with configs */ - fl->data = xrealloc(fl->data, sizeof(struct stat)); + fl->data = xmalloc(sizeof(struct stat)); memcpy(fl->data, &st, sizeof(struct stat)); } @@ -850,6 +892,7 @@ int main(int argc, char **argv) } else { scan_dir_find_ch_files("."); } + store_keys(); return 0; } @@ -881,30 +924,6 @@ static char *bb_asprint(const char *format, ...) } /* partial libbb routine as is */ -static void *xmalloc(size_t size) -{ - void *p = malloc(size); - - if(p == NULL) - bb_error_d(msg_enomem); - return p; -} - -static void *xrealloc(void *p, size_t size) { - p = realloc(p, size); - if(p == NULL) - bb_error_d(msg_enomem); - return p; -} - -static char *bb_xstrdup(const char *s) -{ - char *r = strdup(s); - - if(r == NULL) - bb_error_d(msg_enomem); - return r; -} static char *bb_simplify_path(const char *path) { |