/*
- * Another dependences for Makefile mashine generator
+ * Another dependences for Makefile fast mashine generator
*
* Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru>
*
* -w (show warning if include files not found)
* -k include/config (default: INCLUDE_CONFIG_PATH)
* -c include/config.h (configs, default: INCLUDE_CONFIG_KEYS_PATH)
+ * dirs_for_scan (default ".")
*/
#define LOCAL_INCLUDE_PATH "include"
struct BB_KEYS *next;
} 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 */
-
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)));
/* for lexical analyzier */
static bb_key_t *key_top;
+static llist_t *configs;
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 */
+/* for speed triks */
+static char first_chars[257]; /* + L_EOF */
-#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);
+static int pagesizem1;
+static size_t mema_id = 128; /* first allocated for id */
+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 S 0 /* start state */
#define STR '"' /* string */
#define CHR '\'' /* char */
-#define REM '*' /* block comment */
+#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 DK 'K' /* #define KEY... (config mode) */
-#define DV 'V' /* #define KEY "... or #define KEY '... */
-#define NLC 'n' /* \+\n */
-#define ANY '?' /* skip unparsed . */
+#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) ? EOF : *optr++; } while(0)
+#define getc1() do { c = (optr >= oend) ? L_EOF : *optr++; } while(0)
#define ungetc1() optr--
-#define put_id(c) do { if(id_len == mema_id) \
- id = xrealloc(id, mema_id += 16); \
+#define put_id(c) do { if(id_len == local_mema_id) \
+ id = xrealloc(id, local_mema_id += 16); \
id[id_len++] = c; } while(0)
/* 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 prev_state = EOF;
+ int c = L_EOF; /* stupid initialize */
+ int prev_state = L_EOF;
int called;
int state;
int line;
- static size_t mema_id;
- static char *id_s;
- char *id;
+ 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;
int fd;
char *map;
int mapsize;
- {
- /* stolen from mkdep by Linus Torvalds */
- int pagesizem1 = getpagesize() - 1;
- struct stat st;
- fd = open(fname, O_RDONLY);
- if(fd < 0) {
+ fd = open(fname, O_RDONLY);
+ if(fd < 0) {
perror(fname);
return;
- }
- fstat(fd, &st);
- if (st.st_size == 0)
- bb_error_d("%s is empty", fname);
- mapsize = st.st_size;
- mapsize = (mapsize+pagesizem1) & ~pagesizem1;
- map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
- if ((long) map == -1)
+ }
+ mapsize = (fsize+pagesizem1) & ~pagesizem1;
+ map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
+ if ((long) map == -1)
bb_error_d("%s: mmap: %m", fname);
- /* hereinafter is my */
- optr = (unsigned char *)map;
- oend = optr + st.st_size;
- }
+ optr = (unsigned char *)map;
+ oend = optr + fsize;
- if(id_s == NULL) {
- /* fist allocate */
- id_s = xmalloc(mema_id=128);
- }
- id = id_s;
line = 1;
called = state = S;
if(state == LI) {
parse_inc(id, fname);
} else {
- /*
- if(val[0] == '\0')
- yy_error_d("expected value");
- */
+ /* #define KEY "[VAL]" */
parse_conf_opt(id, val, (optr - start));
}
state = S;
while(c == ' ' || c == '\t')
getc1();
- if(c == '\\') {
+ if(c == BS) {
getc1();
if(c == '\n') {
/* \\\n eat continued */
continue;
}
ungetc1();
- c = '\\';
+ c = BS;
}
if(state == S) {
- while(c <= ' ' && c != EOF) {
- /* <S>[\000- ]+ */
+ while(first_chars[c] == ANY) {
+ /* <S>unparsed */
if(c == '\n')
line++;
getc1();
}
- if(c == EOF) {
+ if(c == L_EOF) {
/* <S><<EOF>> */
+ id_s = id;
+ mema_id = local_mema_id;
munmap(map, mapsize);
close(fd);
return;
}
- if(c == '/') {
+ if(c == REM) {
/* <S>/ */
- getc1();
- if(c == '/') {
+ getc1(); /* eat <S>/ */
+ if(c == REM) {
/* <S>"//"[^\n]* */
- do getc1(); while(c != '\n' && c != EOF);
+ do getc1(); while(c != '\n' && c != L_EOF);
} else if(c == '*') {
/* <S>[/][*] */
called = S;
state = REM;
}
- /* eat <S>/ */
- } else if(c == '#') {
- /* <S>\"|\'|# */
+ } else if(c == POUND) {
+ /* <S># */
start = optr - 1;
state = c;
} else if(c == STR || c == CHR) {
- /* <S>\"|\'|# */
+ /* <S>\"|\' */
val = NULL;
called = S;
state = c;
- } else if(ISALNUM(c)) {
+ } else if(c != BS) {
/* <S>[A-Z_a-z0-9] */
/* trick for fast drop id
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]+ */
do getc1(); while(ISALNUM(c));
} else {
getc1();
} while(ISALNUM(c));
put_id(0);
- find_already(key_top, id, CHECK_ONLY);
+ check_key(key_top, id);
}
} else {
- /* <S>. */
- prev_state = ANY;
+ /* <S>\\ */
+ prev_state = c;
}
continue;
}
if(called != S)
yy_error_d("unexpected newline");
line++;
- } else if(c == EOF)
+ } else if(c == L_EOF)
yy_error_d("unexpected EOF");
getc1();
}
/* <REM>[*] */
getc1();
- if(c == '/') {
+ if(c == REM) {
/* <REM>[*][/] */
state = called;
break;
if(state == STR || state == CHR) {
for(;;) {
/* <STR,CHR>\n|<<EOF>> */
- if(c == '\n' || c == EOF)
+ if(c == '\n' || c == L_EOF)
yy_error_d("unterminating");
- if(c == '\\') {
+ if(c == BS) {
/* <STR,CHR>\\ */
getc1();
- if(c != '\\' && c != '\n' && c != state) {
+ if(c != BS && c != '\n' && c != state) {
/* another usage \ in str or char */
- if(c == EOF)
+ if(c == L_EOF)
yy_error_d("unexpected EOF");
if(val)
put_id(c);
} else if(c == state) {
/* <STR>\" or <CHR>\' */
if(called == DV)
- put_id(c);
+ put_id(c); /* #define KEY "VALUE"<- */
state = called;
break;
} else if(val)
}
/* begin preprocessor states */
- if(c == EOF)
+ if(c == L_EOF)
yy_error_d("unexpected EOF");
- if(c == '/') {
+ if(c == REM) {
/* <#.*>/ */
getc1();
- if(c == '/')
+ if(c == REM)
yy_error_d("detect // in preprocessor line");
if(c == '*') {
/* <#.*>[/][*] */
/* hmm, #.*[/] */
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[] = {
"define", "undef", "include", ""
};
const char * const *str_type;
id_len = 0;
- while(ISALNUM(c)) {
- put_id(c);
- getc1();
- }
+ do { put_id(c); getc1(); } while(ISALNUM(c));
put_id(0);
for(str_type = preproc; (state = **str_type); str_type++) {
if(*id == state && strcmp(id, *str_type) == 0)
break;
}
/* to S if another #directive */
- ungetc1();
id_len = 0; /* common for save */
- continue;
+ }
+ ungetc1();
+ continue;
}
if(state == I) {
if(c == STR) {
/* <I>\" */
val = id;
- state = STR;
called = LI;
- continue;
+ state = STR;
+ } else {
+ /* another (may be wrong) #include ... */
+ ungetc1();
+ state = S;
}
- /* another (may be wrong) #include ... */
- ungetc1();
- state = S;
continue;
}
if(state == D || state == U) {
- while(ISALNUM(c)) {
- if(flg_config_include) {
- /* save KEY from #"define"|"undef" ... */
- put_id(c);
- }
- getc1();
- }
- if(!flg_config_include) {
+ if(configs == NULL) {
+ /* ignore depend with #define or #undef KEY */
+ while(ISALNUM(c))
+ getc1();
state = S;
} else {
+ /* save KEY from #"define"|"undef" ... */
+ while(ISALNUM(c)) {
+ put_id(c);
+ getc1();
+ }
if(!id_len)
yy_error_d("expected identificator");
put_id(0);
continue;
}
if(state == DK) {
- /* #define (config mode) */
+ /* #define KEY[ ] (config mode) */
val = id + id_len;
if(c == STR || c == CHR) {
/* define KEY "... or define KEY '... */
continue;
}
while(ISALNUM(c)) {
+ /* VALUE */
put_id(c);
getc1();
}
static void show_usage(void) __attribute__ ((noreturn));
static void show_usage(void)
{
- bb_error_d("Usage: [-I local_include_path] [-dw] "
- "[-k path_for_store_keys] [-s skip_file]");
+ bb_error_d("Usage: [-I local_include_paths] [-dw] "
+ "[-k path_for_store_keys] [-s skip_file] [dirs]");
}
static const char *kp;
+static size_t kp_len;
static llist_t *Iop;
static bb_key_t *Ifound;
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;
+ bb_key_t *cur;
- for(cur = k; cur; cur = cur->next) {
- if(strcmp(cur->keyname, nk) == 0) {
- cur->checked = 1;
- return NULL;
- }
+ for(cur = k; cur; cur = cur->next) {
+ if(strcmp(cur->keyname, nk) == 0) {
+ cur->checked = 1;
+ return cur;
}
- if(flg_save_new == CHECK_ONLY)
- return NULL;
- cur = xmalloc(sizeof(bb_key_t));
- cur->keyname = bb_xstrdup(nk);
+ }
+ return NULL;
+}
+
+static bb_key_t *make_new_key(bb_key_t *k, const char *nk)
+{
+ bb_key_t *cur;
+ size_t nk_size;
+
+ nk_size = strlen(nk) + 1;
+ cur = xmalloc(sizeof(bb_key_t) + nk_size);
+ cur->keyname = memcpy(cur + 1, nk, nk_size);
cur->checked = 1;
cur->next = k;
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;
- int ok = 0;
+ char *ok;
if(stat(p_i, &st) == 0) {
- li->stored_path = bb_simplify_path(p_i);
- ok = 1;
+ ok = li->stored_path = bb_simplify_path(p_i);
+ } else {
+ ok = NULL;
}
free(p_i);
return ok;
char *p_i;
llist_t *lo;
- if((li = find_already(Ifound, include, MAKE_NEW)) == NULL)
+ li = check_key(Ifound, include);
+ if(li)
return;
- Ifound = li;
+ Ifound = li = make_new_key(Ifound, include);
+
if(include[0] != '/') {
/* relative */
int w;
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 */
char *s, *p;
struct stat st;
static char *record_buf;
static char *r_cmp;
static size_t r_sz;
+ ssize_t rw_ret;
+
+ cur = make_new_key(key_top, opt);
recordsz += 2; /* \n\0 */
if(recordsz > r_sz) {
}
s = record_buf;
/* may be short count " " */
- if(val)
- recordsz = sprintf(s, "#define %s%s%s\n", opt, (*val ? " " : ""), val);
- else
+ if(val) {
+ if(*val == '\0') {
+ 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);
- 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++) {
if(*p >= 'A' && *p <= 'Z')
*p = *p - 'A' + 'a';
p = bb_asprint("%s/%s.h", kp, opt);
cur->stored_path = opt = p;
if(stat(opt, &st)) {
+ p += kp_len;
while(*++p) {
/* Auto-create directories. */
if (*p == '/') {
}
} else {
/* found */
- if(st.st_size == recordsz) {
+ if(st.st_size == (off_t)recordsz) {
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);
close(fd);
cmp_ok = memcmp(s, r_cmp, recordsz) == 0;
}
if(!cmp_ok) {
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);
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;
} else {
/* present already */
- for(cur = key_top; cur; cur = cur->next) {
- if(strcmp(cur->keyname, opt) == 0) {
- cur->checked = 0;
- if(cur->value == NULL && val == NULL)
- return;
- if((cur->value == NULL && val != NULL) ||
- (cur->value != NULL && val == NULL) ||
- strcmp(cur->value, val))
- fprintf(stderr, "Warning: redefined %s\n", opt);
- return;
- }
- }
+ if((cur->value == NULL && val != NULL) ||
+ (cur->value != NULL && val == NULL) ||
+ (cur->value != NULL && val != NULL && strcmp(cur->value, val)))
+ fprintf(stderr, "Warning: redefined %s\n", opt);
}
+ /* 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;
for(cur = k; cur; cur = cur->next) {
if(cur->checked && cur->stored_path) {
if(first) {
- const char *ext;
-
- 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);
- }
+ printf("\n%s:", name);
first = 0;
} else {
printf(" \\\n ");
}
static llist_t *files;
+static struct stat st_kp;
+
+static char *dir_and_entry;
-static llist_t *filter_chd(const char *fe, const char *p, llist_t *pdirs)
+static char *
+filter_chd(const char *fe, const char *p, size_t dirlen)
{
struct stat st;
char *fp;
char *afp;
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 == '.')
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)) {
fprintf(stderr, "Warning: stat(%s): %m", fp);
- free(fp);
return NULL;
}
if(S_ISREG(st.st_mode)) {
- const char *e = strrchr(fe, '.');
-
- if(e == NULL || !((e[1]=='c' || e[1]=='h') && e[2]=='\0')) {
+ afp = fp + df_sz - 3;
+ if(*afp++ != '.' || (*afp != 'c' && *afp != 'h')) {
/* direntry is regular file, but is not *.[ch] */
- free(fp);
return NULL;
}
- } 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 (st.st_size == 0) {
+ fprintf(stderr, "Warning: %s is empty\n", fp);
+ return NULL;
}
+ } else {
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);
+ /* buff is returned, begin of zero allocate */
+ dir_and_entry = NULL;
+ dir_and_entry_sz = 0;
+ return fp;
}
/* hmm, is device! */
- free(fp);
return NULL;
}
afp = bb_simplify_path(fp);
if(cfl->data && strcmp(cfl->data, afp) == 0) {
/* parse configs.h */
free(afp);
- c_lex(fp, 1);
- free(fp);
+ c_lex(fp, st.st_size);
free(cfl->data);
cfl->data = NULL;
return NULL;
}
}
- free(fp);
/* 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;
}
llist_t *d;
struct dirent *de;
DIR *dir;
+ size_t dirlen;
dirs = llist_add_to(NULL, p);
/* emulate recursive */
dir = opendir(dirs->data);
if (dir == NULL)
fprintf(stderr, "Warning: opendir(%s): %m", dirs->data);
+ dirlen = strlen(dirs->data);
while ((de = readdir(dir)) != NULL) {
- d = filter_chd(de->d_name, dirs->data, d_add);
- if(d)
- d_add = d;
+ char *found_dir = filter_chd(de->d_name, dirs->data, dirlen);
+
+ if(found_dir)
+ d_add = llist_add_to(d_add, found_dir);
}
closedir(dir);
if(dirs->data != 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);
- }
- }
}
+static char *pwd;
+
int main(int argc, char **argv)
{
int generate_dep = 1;
int i;
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) {
switch(i) {
case 'I':
show_usage();
}
}
- if(argc > optind)
- show_usage();
-
/* defaults */
if(kp == NULL)
kp = bb_simplify_path(INCLUDE_CONFIG_PATH);
s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH);
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) {
- c_lex(fl->data, 0);
+ file_list_t *t = (file_list_t *)(fl->data);
+ c_lex(t->name, t->size);
if(generate_dep) {
- i = show_dep(1, Ifound, fl->data);
- i = show_dep(i, key_top, fl->data);
+ if(t->ext[0] == 'c') {
+ /* *.c -> *.o */
+ t->ext[0] = 'o';
+ }
+ i = show_dep(1, Ifound, t->name);
+ i = show_dep(i, key_top, t->name);
if(i == 0)
putchar('\n');
}
return 0;
}
+/* partial and simplify libbb routine */
static void bb_error_d(const char *s, ...)
{
va_list p;
char *s, *start, *p;
if (path[0] == '/')
- start = bb_xstrdup(path);
+ start = bb_xstrdup(path);
else {
- static char *pwd;
-
- 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);
+ /* is not libbb, but this program have not chdir() */
+ start = bb_asprint("%s/%s", pwd, path);
}
p = s = start;