/*
- * 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,
*
* 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"
#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)
#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;
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 */
}
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
} 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");
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" ... */
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) {
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;
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);
}
}
/* 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;
}
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;
}
}
+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)
{
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);
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 */
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));
}
} else {
scan_dir_find_ch_files(".");
}
+ store_keys();
return 0;
}
}
/* 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)
{