bb_mkdep release. speed up *3, clearing, more comments

This commit is contained in:
"Vladimir N. Oleynik" 2005-09-13 16:50:53 +00:00
parent 6943a9489e
commit 676e95ea3d
2 changed files with 267 additions and 219 deletions

View File

@ -1,2 +1 @@
mkdep bb_mkdep
split-include

View File

@ -1,5 +1,5 @@
/* /*
* Another dependences for Makefile mashine generator * Another dependences for Makefile fast mashine generator
* *
* Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru> * Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru>
* *
@ -19,6 +19,7 @@
* -w (show warning if include files not found) * -w (show warning if include files not found)
* -k include/config (default: INCLUDE_CONFIG_PATH) * -k include/config (default: INCLUDE_CONFIG_PATH)
* -c include/config.h (configs, default: INCLUDE_CONFIG_KEYS_PATH) * -c include/config.h (configs, default: INCLUDE_CONFIG_KEYS_PATH)
* dirs_for_scan (default ".")
*/ */
#define LOCAL_INCLUDE_PATH "include" #define LOCAL_INCLUDE_PATH "include"
@ -47,9 +48,13 @@ typedef struct BB_KEYS {
struct BB_KEYS *next; struct BB_KEYS *next;
} bb_key_t; } bb_key_t;
typedef struct FILE_LIST {
char *name;
char *ext; /* *.c or *.h, point to last char */
long size;
} file_list_t;
/* partial and simplify libbb routine */ /* partial and simplify libbb routine */
static void bb_error_d(const char *s, ...) __attribute__ ((noreturn, 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))); static char * bb_asprint(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
@ -66,15 +71,20 @@ static char *bb_simplify_path(const char *path);
/* for lexical analyzier */ /* for lexical analyzier */
static bb_key_t *key_top; static bb_key_t *key_top;
static llist_t *configs;
static void parse_inc(const char *include, const char *fname); static void parse_inc(const char *include, const char *fname);
static void parse_conf_opt(char *opt, const char *val, size_t rsz); static void parse_conf_opt(char *opt, const char *val, size_t rsz);
static char first_char_conf_opts[256]; /* for speed */ /* for speed triks */
static char first_chars[257]; /* + L_EOF */
#define CHECK_ONLY 0 static int pagesizem1;
#define MAKE_NEW 1 static size_t mema_id = 128; /* first allocated for id */
static bb_key_t *find_already(bb_key_t *k, const char *nk, int flg_save_new); static char *id_s;
static bb_key_t *check_key(bb_key_t *k, const char *nk);
static bb_key_t *make_new_key(bb_key_t *k, const char *nk);
#define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s) #define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s)
@ -82,40 +92,41 @@ static bb_key_t *find_already(bb_key_t *k, const char *nk, int flg_save_new);
#define S 0 /* start state */ #define S 0 /* start state */
#define STR '"' /* string */ #define STR '"' /* string */
#define CHR '\'' /* char */ #define CHR '\'' /* char */
#define REM '*' /* block comment */ #define REM '/' /* block comment */
#define BS '\\' /* back slash */
#define POUND '#' /* # */ #define POUND '#' /* # */
#define I 'i' /* #include preprocessor`s directive */ #define I 'i' /* #include preprocessor`s directive */
#define D 'd' /* #define preprocessor`s directive */ #define D 'd' /* #define preprocessor`s directive */
#define U 'u' /* #undef preprocessor`s directive */ #define U 'u' /* #undef preprocessor`s directive */
#define LI 'I' /* #include "... */ #define LI 'I' /* #include "... */
#define DK 'K' /* #define KEY... (config mode) */ #define DK 'K' /* #define KEY... (config mode) */
#define DV 'V' /* #define KEY "... or #define KEY '... */ #define DV 'V' /* #define KEY "VALUE or #define KEY 'VALUE */
#define NLC 'n' /* \+\n */ #define NLC 'n' /* \ and \n */
#define ANY '?' /* skip unparsed . */ #define ANY '*' /* any unparsed chars */
#define L_EOF 256
/* [A-Z_a-z] */ /* [A-Z_a-z] */
#define ID(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') #define ID(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_')
/* [A-Z_a-z0-9] */ /* [A-Z_a-z0-9] */
#define ISALNUM(c) (ID(c) || (c >= '0' && c <= '9')) #define ISALNUM(c) (ID(c) || (c >= '0' && c <= '9'))
#define getc1() do { c = (optr >= oend) ? EOF : *optr++; } while(0) #define getc1() do { c = (optr >= oend) ? L_EOF : *optr++; } while(0)
#define ungetc1() optr-- #define ungetc1() optr--
#define put_id(c) do { if(id_len == mema_id) \ #define put_id(c) do { if(id_len == local_mema_id) \
id = xrealloc(id, mema_id += 16); \ id = xrealloc(id, local_mema_id += 16); \
id[id_len++] = c; } while(0) id[id_len++] = c; } while(0)
/* stupid C lexical analizator */ /* stupid C lexical analizator */
static void c_lex(const char *fname, int flg_config_include) static void c_lex(const char *fname, long fsize)
{ {
int c = EOF; /* stupid initialize */ int c = L_EOF; /* stupid initialize */
int prev_state = EOF; int prev_state = L_EOF;
int called; int called;
int state; int state;
int line; int line;
static size_t mema_id; char *id = id_s;
static char *id_s; size_t local_mema_id = mema_id;
char *id;
size_t id_len = 0; /* stupid initialize */ size_t id_len = 0; /* stupid initialize */
char *val = NULL; char *val = NULL;
unsigned char *optr, *oend; unsigned char *optr, *oend;
@ -124,35 +135,20 @@ static void c_lex(const char *fname, int flg_config_include)
int fd; int fd;
char *map; char *map;
int mapsize; int mapsize;
{
/* stolen from mkdep by Linus Torvalds */
int pagesizem1 = getpagesize() - 1;
struct stat st;
fd = open(fname, O_RDONLY); fd = open(fname, O_RDONLY);
if(fd < 0) { if(fd < 0) {
perror(fname); perror(fname);
return; return;
} }
fstat(fd, &st); mapsize = (fsize+pagesizem1) & ~pagesizem1;
if (st.st_size == 0) map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
bb_error_d("%s is empty", fname); if ((long) map == -1)
mapsize = st.st_size;
mapsize = (mapsize+pagesizem1) & ~pagesizem1;
map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
if ((long) map == -1)
bb_error_d("%s: mmap: %m", fname); bb_error_d("%s: mmap: %m", fname);
/* hereinafter is my */ optr = (unsigned char *)map;
optr = (unsigned char *)map; oend = optr + fsize;
oend = optr + st.st_size;
}
if(id_s == NULL) {
/* fist allocate */
id_s = xmalloc(mema_id=128);
}
id = id_s;
line = 1; line = 1;
called = state = S; called = state = S;
@ -163,10 +159,7 @@ static void c_lex(const char *fname, int flg_config_include)
if(state == LI) { if(state == LI) {
parse_inc(id, fname); parse_inc(id, fname);
} else { } else {
/* /* #define KEY "[VAL]" */
if(val[0] == '\0')
yy_error_d("expected value");
*/
parse_conf_opt(id, val, (optr - start)); parse_conf_opt(id, val, (optr - start));
} }
state = S; state = S;
@ -180,7 +173,7 @@ static void c_lex(const char *fname, int flg_config_include)
while(c == ' ' || c == '\t') while(c == ' ' || c == '\t')
getc1(); getc1();
if(c == '\\') { if(c == BS) {
getc1(); getc1();
if(c == '\n') { if(c == '\n') {
/* \\\n eat continued */ /* \\\n eat continued */
@ -189,49 +182,50 @@ static void c_lex(const char *fname, int flg_config_include)
continue; continue;
} }
ungetc1(); ungetc1();
c = '\\'; c = BS;
} }
if(state == S) { if(state == S) {
while(c <= ' ' && c != EOF) { while(first_chars[c] == ANY) {
/* <S>[\000- ]+ */ /* <S>unparsed */
if(c == '\n') if(c == '\n')
line++; line++;
getc1(); getc1();
} }
if(c == EOF) { if(c == L_EOF) {
/* <S><<EOF>> */ /* <S><<EOF>> */
id_s = id;
mema_id = local_mema_id;
munmap(map, mapsize); munmap(map, mapsize);
close(fd); close(fd);
return; return;
} }
if(c == '/') { if(c == REM) {
/* <S>/ */ /* <S>/ */
getc1(); getc1(); /* eat <S>/ */
if(c == '/') { if(c == REM) {
/* <S>"//"[^\n]* */ /* <S>"//"[^\n]* */
do getc1(); while(c != '\n' && c != EOF); do getc1(); while(c != '\n' && c != L_EOF);
} else if(c == '*') { } else if(c == '*') {
/* <S>[/][*] */ /* <S>[/][*] */
called = S; called = S;
state = REM; state = REM;
} }
/* eat <S>/ */ } else if(c == POUND) {
} else if(c == '#') { /* <S># */
/* <S>\"|\'|# */
start = optr - 1; start = optr - 1;
state = c; state = c;
} else if(c == STR || c == CHR) { } else if(c == STR || c == CHR) {
/* <S>\"|\'|# */ /* <S>\"|\' */
val = NULL; val = NULL;
called = S; called = S;
state = c; state = c;
} else if(ISALNUM(c)) { } else if(c != BS) {
/* <S>[A-Z_a-z0-9] */ /* <S>[A-Z_a-z0-9] */
/* trick for fast drop id /* trick for fast drop id
if key with this first char undefined */ if key with this first char undefined */
if(first_char_conf_opts[c] == 0) { if(first_chars[c] == 0) {
/* skip <S>[A-Z_a-z0-9]+ */ /* skip <S>[A-Z_a-z0-9]+ */
do getc1(); while(ISALNUM(c)); do getc1(); while(ISALNUM(c));
} else { } else {
@ -242,11 +236,11 @@ static void c_lex(const char *fname, int flg_config_include)
getc1(); getc1();
} while(ISALNUM(c)); } while(ISALNUM(c));
put_id(0); put_id(0);
find_already(key_top, id, CHECK_ONLY); check_key(key_top, id);
} }
} else { } else {
/* <S>. */ /* <S>\\ */
prev_state = ANY; prev_state = c;
} }
continue; continue;
} }
@ -259,13 +253,13 @@ static void c_lex(const char *fname, int flg_config_include)
if(called != S) if(called != S)
yy_error_d("unexpected newline"); yy_error_d("unexpected newline");
line++; line++;
} else if(c == EOF) } else if(c == L_EOF)
yy_error_d("unexpected EOF"); yy_error_d("unexpected EOF");
getc1(); getc1();
} }
/* <REM>[*] */ /* <REM>[*] */
getc1(); getc1();
if(c == '/') { if(c == REM) {
/* <REM>[*][/] */ /* <REM>[*][/] */
state = called; state = called;
break; break;
@ -276,14 +270,14 @@ static void c_lex(const char *fname, int flg_config_include)
if(state == STR || state == CHR) { if(state == STR || state == CHR) {
for(;;) { for(;;) {
/* <STR,CHR>\n|<<EOF>> */ /* <STR,CHR>\n|<<EOF>> */
if(c == '\n' || c == EOF) if(c == '\n' || c == L_EOF)
yy_error_d("unterminating"); yy_error_d("unterminating");
if(c == '\\') { if(c == BS) {
/* <STR,CHR>\\ */ /* <STR,CHR>\\ */
getc1(); getc1();
if(c != '\\' && c != '\n' && c != state) { if(c != BS && c != '\n' && c != state) {
/* another usage \ in str or char */ /* another usage \ in str or char */
if(c == EOF) if(c == L_EOF)
yy_error_d("unexpected EOF"); yy_error_d("unexpected EOF");
if(val) if(val)
put_id(c); put_id(c);
@ -298,7 +292,7 @@ static void c_lex(const char *fname, int flg_config_include)
} else if(c == state) { } else if(c == state) {
/* <STR>\" or <CHR>\' */ /* <STR>\" or <CHR>\' */
if(called == DV) if(called == DV)
put_id(c); put_id(c); /* #define KEY "VALUE"<- */
state = called; state = called;
break; break;
} else if(val) } else if(val)
@ -310,12 +304,12 @@ static void c_lex(const char *fname, int flg_config_include)
} }
/* begin preprocessor states */ /* begin preprocessor states */
if(c == EOF) if(c == L_EOF)
yy_error_d("unexpected EOF"); yy_error_d("unexpected EOF");
if(c == '/') { if(c == REM) {
/* <#.*>/ */ /* <#.*>/ */
getc1(); getc1();
if(c == '/') if(c == REM)
yy_error_d("detect // in preprocessor line"); yy_error_d("detect // in preprocessor line");
if(c == '*') { if(c == '*') {
/* <#.*>[/][*] */ /* <#.*>[/][*] */
@ -326,51 +320,55 @@ static void c_lex(const char *fname, int flg_config_include)
/* hmm, #.*[/] */ /* hmm, #.*[/] */
yy_error_d("strange preprocessor line"); yy_error_d("strange preprocessor line");
} }
if(state == '#') { if(state == POUND) {
if(c != 'd' && c != 'u' && c != 'i') {
while(ISALNUM(c))
getc1();
state = S;
} else {
static const char * const preproc[] = { static const char * const preproc[] = {
"define", "undef", "include", "" "define", "undef", "include", ""
}; };
const char * const *str_type; const char * const *str_type;
id_len = 0; id_len = 0;
while(ISALNUM(c)) { do { put_id(c); getc1(); } while(ISALNUM(c));
put_id(c);
getc1();
}
put_id(0); put_id(0);
for(str_type = preproc; (state = **str_type); str_type++) { for(str_type = preproc; (state = **str_type); str_type++) {
if(*id == state && strcmp(id, *str_type) == 0) if(*id == state && strcmp(id, *str_type) == 0)
break; break;
} }
/* to S if another #directive */ /* to S if another #directive */
ungetc1();
id_len = 0; /* common for save */ id_len = 0; /* common for save */
continue; }
ungetc1();
continue;
} }
if(state == I) { if(state == I) {
if(c == STR) { if(c == STR) {
/* <I>\" */ /* <I>\" */
val = id; val = id;
state = STR;
called = LI; called = LI;
continue; state = STR;
} else {
/* another (may be wrong) #include ... */
ungetc1();
state = S;
} }
/* another (may be wrong) #include ... */
ungetc1();
state = S;
continue; continue;
} }
if(state == D || state == U) { if(state == D || state == U) {
while(ISALNUM(c)) { if(configs == NULL) {
if(flg_config_include) { /* ignore depend with #define or #undef KEY */
/* save KEY from #"define"|"undef" ... */ while(ISALNUM(c))
put_id(c); getc1();
}
getc1();
}
if(!flg_config_include) {
state = S; state = S;
} else { } else {
/* save KEY from #"define"|"undef" ... */
while(ISALNUM(c)) {
put_id(c);
getc1();
}
if(!id_len) if(!id_len)
yy_error_d("expected identificator"); yy_error_d("expected identificator");
put_id(0); put_id(0);
@ -386,7 +384,7 @@ static void c_lex(const char *fname, int flg_config_include)
continue; continue;
} }
if(state == DK) { if(state == DK) {
/* #define (config mode) */ /* #define KEY[ ] (config mode) */
val = id + id_len; val = id + id_len;
if(c == STR || c == CHR) { if(c == STR || c == CHR) {
/* define KEY "... or define KEY '... */ /* define KEY "... or define KEY '... */
@ -396,6 +394,7 @@ static void c_lex(const char *fname, int flg_config_include)
continue; continue;
} }
while(ISALNUM(c)) { while(ISALNUM(c)) {
/* VALUE */
put_id(c); put_id(c);
getc1(); getc1();
} }
@ -410,43 +409,51 @@ static void c_lex(const char *fname, int flg_config_include)
static void show_usage(void) __attribute__ ((noreturn)); static void show_usage(void) __attribute__ ((noreturn));
static void show_usage(void) static void show_usage(void)
{ {
bb_error_d("Usage: [-I local_include_path] [-dw] " bb_error_d("Usage: [-I local_include_paths] [-dw] "
"[-k path_for_store_keys] [-s skip_file]"); "[-k path_for_store_keys] [-s skip_file] [dirs]");
} }
static const char *kp; static const char *kp;
static size_t kp_len;
static llist_t *Iop; static llist_t *Iop;
static bb_key_t *Ifound; static bb_key_t *Ifound;
static int noiwarning; static int noiwarning;
static llist_t *configs;
static bb_key_t *find_already(bb_key_t *k, const char *nk, int flg_save_new) static bb_key_t *check_key(bb_key_t *k, const char *nk)
{
bb_key_t *cur;
for(cur = k; cur; cur = cur->next) {
if(strcmp(cur->keyname, nk) == 0) {
cur->checked = 1;
return cur;
}
}
return NULL;
}
static bb_key_t *make_new_key(bb_key_t *k, const char *nk)
{ {
bb_key_t *cur; bb_key_t *cur;
size_t nk_size;
for(cur = k; cur; cur = cur->next) { nk_size = strlen(nk) + 1;
if(strcmp(cur->keyname, nk) == 0) { cur = xmalloc(sizeof(bb_key_t) + nk_size);
cur->checked = 1; cur->keyname = memcpy(cur + 1, nk, nk_size);
return NULL;
}
}
if(flg_save_new == CHECK_ONLY)
return NULL;
cur = xmalloc(sizeof(bb_key_t));
cur->keyname = bb_xstrdup(nk);
cur->checked = 1; cur->checked = 1;
cur->next = k; cur->next = k;
return cur; return cur;
} }
static int store_include_fullpath(char *p_i, bb_key_t *li) static inline char *store_include_fullpath(char *p_i, bb_key_t *li)
{ {
struct stat st; struct stat st;
int ok = 0; char *ok;
if(stat(p_i, &st) == 0) { if(stat(p_i, &st) == 0) {
li->stored_path = bb_simplify_path(p_i); ok = li->stored_path = bb_simplify_path(p_i);
ok = 1; } else {
ok = NULL;
} }
free(p_i); free(p_i);
return ok; return ok;
@ -458,9 +465,11 @@ static void parse_inc(const char *include, const char *fname)
char *p_i; char *p_i;
llist_t *lo; llist_t *lo;
if((li = find_already(Ifound, include, MAKE_NEW)) == NULL) li = check_key(Ifound, include);
if(li)
return; return;
Ifound = li; Ifound = li = make_new_key(Ifound, include);
if(include[0] != '/') { if(include[0] != '/') {
/* relative */ /* relative */
int w; int w;
@ -490,9 +499,10 @@ static void parse_inc(const char *include, const char *fname)
static void parse_conf_opt(char *opt, const char *val, size_t recordsz) static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
{ {
bb_key_t *cur = find_already(key_top, opt, MAKE_NEW); bb_key_t *cur;
if(cur != NULL) { cur = check_key(key_top, opt);
if(cur == NULL) {
/* new key, check old key if present after previous usage */ /* new key, check old key if present after previous usage */
char *s, *p; char *s, *p;
struct stat st; struct stat st;
@ -501,6 +511,9 @@ static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
static char *record_buf; static char *record_buf;
static char *r_cmp; static char *r_cmp;
static size_t r_sz; static size_t r_sz;
ssize_t rw_ret;
cur = make_new_key(key_top, opt);
recordsz += 2; /* \n\0 */ recordsz += 2; /* \n\0 */
if(recordsz > r_sz) { if(recordsz > r_sz) {
@ -509,12 +522,24 @@ static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
} }
s = record_buf; s = record_buf;
/* may be short count " " */ /* may be short count " " */
if(val) if(val) {
recordsz = sprintf(s, "#define %s%s%s\n", opt, (*val ? " " : ""), val); if(*val == '\0') {
else cur->value = "";
recordsz = sprintf(s, "#define %s\n", opt);
} else {
cur->value = bb_xstrdup(val);
recordsz = sprintf(s, "#define %s %s\n", opt, val);
}
} else {
cur->value = NULL;
recordsz = sprintf(s, "#undef %s\n", opt); recordsz = sprintf(s, "#undef %s\n", opt);
first_char_conf_opts[((int)((unsigned char)(*opt)))] = *opt; }
/* key converting [A-Z] -> [a-z] */ /* size_t -> ssize_t :( */
rw_ret = (ssize_t)recordsz;
/* trick, save first char KEY for do fast identify id */
first_chars[(int)*opt] = *opt;
/* key converting [A-Z_] -> [a-z/] */
for(p = opt; *p; p++) { for(p = opt; *p; p++) {
if(*p >= 'A' && *p <= 'Z') if(*p >= 'A' && *p <= 'Z')
*p = *p - 'A' + 'a'; *p = *p - 'A' + 'a';
@ -524,6 +549,7 @@ static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
p = bb_asprint("%s/%s.h", kp, opt); p = bb_asprint("%s/%s.h", kp, opt);
cur->stored_path = opt = p; cur->stored_path = opt = p;
if(stat(opt, &st)) { if(stat(opt, &st)) {
p += kp_len;
while(*++p) { while(*++p) {
/* Auto-create directories. */ /* Auto-create directories. */
if (*p == '/') { if (*p == '/') {
@ -535,9 +561,9 @@ static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
} }
} else { } else {
/* found */ /* found */
if(st.st_size == recordsz) { if(st.st_size == (off_t)recordsz) {
fd = open(opt, O_RDONLY); fd = open(opt, O_RDONLY);
if(fd < 0 || read(fd, r_cmp, recordsz) != recordsz) if(fd < 0 || read(fd, r_cmp, recordsz) < rw_ret)
bb_error_d("%s: %m", opt); bb_error_d("%s: %m", opt);
close(fd); close(fd);
cmp_ok = memcmp(s, r_cmp, recordsz) == 0; cmp_ok = memcmp(s, r_cmp, recordsz) == 0;
@ -545,57 +571,30 @@ static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
} }
if(!cmp_ok) { if(!cmp_ok) {
fd = open(opt, O_WRONLY|O_CREAT|O_TRUNC, 0644); fd = open(opt, O_WRONLY|O_CREAT|O_TRUNC, 0644);
if(fd < 0 || write(fd, s, recordsz) != recordsz) if(fd < 0 || write(fd, s, recordsz) < rw_ret)
bb_error_d("%s: %m", opt); bb_error_d("%s: %m", opt);
close(fd); close(fd);
} }
/* store only */
cur->checked = 0;
if(val) {
if(*val == '\0') {
cur->value = "";
} else {
cur->value = bb_xstrdup(val);
}
} else {
cur->value = NULL;
}
key_top = cur; key_top = cur;
} else { } else {
/* present already */ /* present already */
for(cur = key_top; cur; cur = cur->next) { if((cur->value == NULL && val != NULL) ||
if(strcmp(cur->keyname, opt) == 0) { (cur->value != NULL && val == NULL) ||
cur->checked = 0; (cur->value != NULL && val != NULL && strcmp(cur->value, val)))
if(cur->value == NULL && val == NULL) fprintf(stderr, "Warning: redefined %s\n", opt);
return;
if((cur->value == NULL && val != NULL) ||
(cur->value != NULL && val == NULL) ||
strcmp(cur->value, val))
fprintf(stderr, "Warning: redefined %s\n", opt);
return;
}
}
} }
/* store only */
cur->checked = 0;
} }
static int show_dep(int first, bb_key_t *k, const char *a) static int show_dep(int first, bb_key_t *k, const char *name)
{ {
bb_key_t *cur; bb_key_t *cur;
for(cur = k; cur; cur = cur->next) { for(cur = k; cur; cur = cur->next) {
if(cur->checked && cur->stored_path) { if(cur->checked && cur->stored_path) {
if(first) { if(first) {
const char *ext; printf("\n%s:", name);
if(*a == '.' && a[1] == '/')
a += 2;
ext = strrchr(a, '.');
if(ext && ext[1] == 'c' && ext[2] == '\0') {
/* *.c -> *.o */
printf("\n%.*s.o:", (ext - a), a);
} else {
printf("\n%s:", a);
}
first = 0; first = 0;
} else { } else {
printf(" \\\n "); printf(" \\\n ");
@ -608,50 +607,56 @@ static int show_dep(int first, bb_key_t *k, const char *a)
} }
static llist_t *files; static llist_t *files;
static struct stat st_kp;
static llist_t *filter_chd(const char *fe, const char *p, llist_t *pdirs) static char *dir_and_entry;
static char *
filter_chd(const char *fe, const char *p, size_t dirlen)
{ {
struct stat st; struct stat st;
char *fp; char *fp;
char *afp; char *afp;
llist_t *cfl; llist_t *cfl;
static struct stat st_kp; file_list_t *f;
size_t df_sz;
static size_t dir_and_entry_sz;
if (*fe == '.') if (*fe == '.')
return NULL; return NULL;
fp = bb_asprint("%s/%s", p, fe);
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);
fp = dir_and_entry;
sprintf(fp, "%s/%s", p, fe);
if(stat(fp, &st)) { if(stat(fp, &st)) {
fprintf(stderr, "Warning: stat(%s): %m", fp); fprintf(stderr, "Warning: stat(%s): %m", fp);
free(fp);
return NULL; return NULL;
} }
if(S_ISREG(st.st_mode)) { if(S_ISREG(st.st_mode)) {
const char *e = strrchr(fe, '.'); afp = fp + df_sz - 3;
if(*afp++ != '.' || (*afp != 'c' && *afp != 'h')) {
if(e == NULL || !((e[1]=='c' || e[1]=='h') && e[2]=='\0')) {
/* direntry is regular file, but is not *.[ch] */ /* direntry is regular file, but is not *.[ch] */
free(fp); return NULL;
}
if (st.st_size == 0) {
fprintf(stderr, "Warning: %s is empty\n", fp);
return NULL; return NULL;
} }
} else { } 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(S_ISDIR(st.st_mode)) {
if (st.st_dev == st_kp.st_dev && st.st_ino == st_kp.st_ino) { 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 */ /* drop scan kp/ directory */
return NULL; return NULL;
} }
return llist_add_to(pdirs, fp); /* buff is returned, begin of zero allocate */
dir_and_entry = NULL;
dir_and_entry_sz = 0;
return fp;
} }
/* hmm, is device! */ /* hmm, is device! */
free(fp);
return NULL; return NULL;
} }
afp = bb_simplify_path(fp); afp = bb_simplify_path(fp);
@ -659,16 +664,18 @@ static llist_t *filter_chd(const char *fe, const char *p, llist_t *pdirs)
if(cfl->data && strcmp(cfl->data, afp) == 0) { if(cfl->data && strcmp(cfl->data, afp) == 0) {
/* parse configs.h */ /* parse configs.h */
free(afp); free(afp);
c_lex(fp, 1); c_lex(fp, st.st_size);
free(fp);
free(cfl->data); free(cfl->data);
cfl->data = NULL; cfl->data = NULL;
return NULL; return NULL;
} }
} }
free(fp);
/* direntry is *.[ch] regular file */ /* direntry is *.[ch] regular file */
files = llist_add_to(files, afp); f = xmalloc(sizeof(file_list_t));
f->name = afp;
f->ext = strrchr(afp, '.') + 1;
f->size = st.st_size;
files = llist_add_to(files, (char *)f);
return NULL; return NULL;
} }
@ -679,6 +686,7 @@ static void scan_dir_find_ch_files(char *p)
llist_t *d; llist_t *d;
struct dirent *de; struct dirent *de;
DIR *dir; DIR *dir;
size_t dirlen;
dirs = llist_add_to(NULL, p); dirs = llist_add_to(NULL, p);
/* emulate recursive */ /* emulate recursive */
@ -688,10 +696,12 @@ static void scan_dir_find_ch_files(char *p)
dir = opendir(dirs->data); dir = opendir(dirs->data);
if (dir == NULL) if (dir == NULL)
fprintf(stderr, "Warning: opendir(%s): %m", dirs->data); fprintf(stderr, "Warning: opendir(%s): %m", dirs->data);
dirlen = strlen(dirs->data);
while ((de = readdir(dir)) != NULL) { while ((de = readdir(dir)) != NULL) {
d = filter_chd(de->d_name, dirs->data, d_add); char *found_dir = filter_chd(de->d_name, dirs->data, dirlen);
if(d)
d_add = d; if(found_dir)
d_add = llist_add_to(d_add, found_dir);
} }
closedir(dir); closedir(dir);
if(dirs->data != p) if(dirs->data != p)
@ -702,15 +712,10 @@ static void scan_dir_find_ch_files(char *p)
} }
dirs = d_add; 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);
}
}
} }
static char *pwd;
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int generate_dep = 1; int generate_dep = 1;
@ -718,6 +723,22 @@ int main(int argc, char **argv)
int i; int i;
llist_t *fl; llist_t *fl;
{
/* for bb_simplify_path */
/* libbb xgetcwd(), this program have not chdir() */
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");
path_max += PATH_INCR;
s = xrealloc (s, path_max);
}
pwd = s;
}
while ((i = getopt(argc, argv, "I:c:dk:w")) > 0) { while ((i = getopt(argc, argv, "I:c:dk:w")) > 0) {
switch(i) { switch(i) {
case 'I': case 'I':
@ -742,9 +763,6 @@ int main(int argc, char **argv)
show_usage(); show_usage();
} }
} }
if(argc > optind)
show_usage();
/* defaults */ /* defaults */
if(kp == NULL) if(kp == NULL)
kp = bb_simplify_path(INCLUDE_CONFIG_PATH); kp = bb_simplify_path(INCLUDE_CONFIG_PATH);
@ -754,13 +772,57 @@ int main(int argc, char **argv)
s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH); s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH);
configs = llist_add_to(configs, s); configs = llist_add_to(configs, s);
} }
/* globals initialize */
/* for c_lex */
pagesizem1 = getpagesize() - 1;
id_s = xmalloc(mema_id);
for(i = 0; i < 256; i++) {
/* set unparsed chars for speed up of parser */
if(!ISALNUM(i) && i != CHR && i != STR &&
i != POUND && i != REM && i != BS)
first_chars[i] = ANY;
}
first_chars[i] = '-'; /* L_EOF */
kp_len = strlen(kp);
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);
/* main loops */
argv += optind;
if(*argv) {
while(*argv)
scan_dir_find_ch_files(*argv++);
} else {
scan_dir_find_ch_files(".");
}
for(fl = configs; fl; fl = fl->link) {
if(fl->data) {
/* configs.h placed outsize of scanned dirs or not "*.ch" */
struct stat st;
if(stat(fl->data, &st))
bb_error_d("stat(%s): %m", fl->data);
c_lex(fl->data, st.st_size);
free(fl->data);
}
}
free(configs);
configs = NULL; /* flag read config --> parse sourses mode */
scan_dir_find_ch_files(".");
for(fl = files; fl; fl = fl->link) { for(fl = files; fl; fl = fl->link) {
c_lex(fl->data, 0); file_list_t *t = (file_list_t *)(fl->data);
c_lex(t->name, t->size);
if(generate_dep) { if(generate_dep) {
i = show_dep(1, Ifound, fl->data); if(t->ext[0] == 'c') {
i = show_dep(i, key_top, fl->data); /* *.c -> *.o */
t->ext[0] = 'o';
}
i = show_dep(1, Ifound, t->name);
i = show_dep(i, key_top, t->name);
if(i == 0) if(i == 0)
putchar('\n'); putchar('\n');
} }
@ -768,6 +830,7 @@ int main(int argc, char **argv)
return 0; return 0;
} }
/* partial and simplify libbb routine */
static void bb_error_d(const char *s, ...) static void bb_error_d(const char *s, ...)
{ {
va_list p; va_list p;
@ -836,24 +899,10 @@ static char *bb_simplify_path(const char *path)
char *s, *start, *p; char *s, *start, *p;
if (path[0] == '/') if (path[0] == '/')
start = bb_xstrdup(path); start = bb_xstrdup(path);
else { else {
static char *pwd; /* is not libbb, but this program have not chdir() */
start = bb_asprint("%s/%s", pwd, path);
if(pwd == NULL) {
/* is not libbb, but this program have not chdir() */
unsigned path_max = 512;
char *cwd = xmalloc (path_max);
#define PATH_INCR 32
while (getcwd (cwd, path_max) == NULL) {
if(errno != ERANGE)
bb_error_d("getcwd: %m");
path_max += PATH_INCR;
cwd = xrealloc (cwd, path_max);
}
pwd = cwd;
}
start = bb_asprint("%s/%s", pwd, path);
} }
p = s = start; p = s = start;