aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvodz <vodz@69ca8d6d-28ef-0310-b511-8ec308f3f277>2005-09-13 16:50:53 +0000
committervodz <vodz@69ca8d6d-28ef-0310-b511-8ec308f3f277>2005-09-13 16:50:53 +0000
commit3723cea7beb7bc3cb0162334c730d4dca1c8e7ed (patch)
tree0392c8888e17ca58d0efd38e727028f0ef71dc77
parent8f5f300ebab513ef6caaa44a5b0808bbe57795bb (diff)
downloadbusybox-w32-3723cea7beb7bc3cb0162334c730d4dca1c8e7ed.tar.gz
busybox-w32-3723cea7beb7bc3cb0162334c730d4dca1c8e7ed.tar.bz2
busybox-w32-3723cea7beb7bc3cb0162334c730d4dca1c8e7ed.zip
bb_mkdep release. speed up *3, clearing, more comments
git-svn-id: svn://busybox.net/trunk/busybox@11446 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--scripts/.cvsignore3
-rw-r--r--scripts/bb_mkdep.c483
2 files changed, 267 insertions, 219 deletions
diff --git a/scripts/.cvsignore b/scripts/.cvsignore
index 07fa550f5..b1ebf606d 100644
--- a/scripts/.cvsignore
+++ b/scripts/.cvsignore
@@ -1,2 +1 @@
1mkdep bb_mkdep
2split-include
diff --git a/scripts/bb_mkdep.c b/scripts/bb_mkdep.c
index 68b3f5bce..ee8456778 100644
--- a/scripts/bb_mkdep.c
+++ b/scripts/bb_mkdep.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Another dependences for Makefile mashine generator 2 * Another dependences for Makefile fast mashine generator
3 * 3 *
4 * Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru> 4 * Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru>
5 * 5 *
@@ -19,6 +19,7 @@
19 * -w (show warning if include files not found) 19 * -w (show warning if include files not found)
20 * -k include/config (default: INCLUDE_CONFIG_PATH) 20 * -k include/config (default: INCLUDE_CONFIG_PATH)
21 * -c include/config.h (configs, default: INCLUDE_CONFIG_KEYS_PATH) 21 * -c include/config.h (configs, default: INCLUDE_CONFIG_KEYS_PATH)
22 * dirs_for_scan (default ".")
22*/ 23*/
23 24
24#define LOCAL_INCLUDE_PATH "include" 25#define LOCAL_INCLUDE_PATH "include"
@@ -47,9 +48,13 @@ typedef struct BB_KEYS {
47 struct BB_KEYS *next; 48 struct BB_KEYS *next;
48} bb_key_t; 49} bb_key_t;
49 50
51typedef struct FILE_LIST {
52 char *name;
53 char *ext; /* *.c or *.h, point to last char */
54 long size;
55} file_list_t;
50 56
51/* partial and simplify libbb routine */ 57/* partial and simplify libbb routine */
52
53static void bb_error_d(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))); 58static void bb_error_d(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
54static char * bb_asprint(const char *format, ...) __attribute__ ((format (printf, 1, 2))); 59static char * bb_asprint(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
55 60
@@ -66,15 +71,20 @@ static char *bb_simplify_path(const char *path);
66 71
67/* for lexical analyzier */ 72/* for lexical analyzier */
68static bb_key_t *key_top; 73static bb_key_t *key_top;
74static llist_t *configs;
69 75
70static void parse_inc(const char *include, const char *fname); 76static void parse_inc(const char *include, const char *fname);
71static void parse_conf_opt(char *opt, const char *val, size_t rsz); 77static void parse_conf_opt(char *opt, const char *val, size_t rsz);
72 78
73static char first_char_conf_opts[256]; /* for speed */ 79/* for speed triks */
80static char first_chars[257]; /* + L_EOF */
74 81
75#define CHECK_ONLY 0 82static int pagesizem1;
76#define MAKE_NEW 1 83static size_t mema_id = 128; /* first allocated for id */
77static bb_key_t *find_already(bb_key_t *k, const char *nk, int flg_save_new); 84static char *id_s;
85
86static bb_key_t *check_key(bb_key_t *k, const char *nk);
87static bb_key_t *make_new_key(bb_key_t *k, const char *nk);
78 88
79#define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s) 89#define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s)
80 90
@@ -82,40 +92,41 @@ static bb_key_t *find_already(bb_key_t *k, const char *nk, int flg_save_new);
82#define S 0 /* start state */ 92#define S 0 /* start state */
83#define STR '"' /* string */ 93#define STR '"' /* string */
84#define CHR '\'' /* char */ 94#define CHR '\'' /* char */
85#define REM '*' /* block comment */ 95#define REM '/' /* block comment */
96#define BS '\\' /* back slash */
86#define POUND '#' /* # */ 97#define POUND '#' /* # */
87#define I 'i' /* #include preprocessor`s directive */ 98#define I 'i' /* #include preprocessor`s directive */
88#define D 'd' /* #define preprocessor`s directive */ 99#define D 'd' /* #define preprocessor`s directive */
89#define U 'u' /* #undef preprocessor`s directive */ 100#define U 'u' /* #undef preprocessor`s directive */
90#define LI 'I' /* #include "... */ 101#define LI 'I' /* #include "... */
91#define DK 'K' /* #define KEY... (config mode) */ 102#define DK 'K' /* #define KEY... (config mode) */
92#define DV 'V' /* #define KEY "... or #define KEY '... */ 103#define DV 'V' /* #define KEY "VALUE or #define KEY 'VALUE */
93#define NLC 'n' /* \+\n */ 104#define NLC 'n' /* \ and \n */
94#define ANY '?' /* skip unparsed . */ 105#define ANY '*' /* any unparsed chars */
95 106
107#define L_EOF 256
96/* [A-Z_a-z] */ 108/* [A-Z_a-z] */
97#define ID(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') 109#define ID(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_')
98/* [A-Z_a-z0-9] */ 110/* [A-Z_a-z0-9] */
99#define ISALNUM(c) (ID(c) || (c >= '0' && c <= '9')) 111#define ISALNUM(c) (ID(c) || (c >= '0' && c <= '9'))
100 112
101#define getc1() do { c = (optr >= oend) ? EOF : *optr++; } while(0) 113#define getc1() do { c = (optr >= oend) ? L_EOF : *optr++; } while(0)
102#define ungetc1() optr-- 114#define ungetc1() optr--
103 115
104#define put_id(c) do { if(id_len == mema_id) \ 116#define put_id(c) do { if(id_len == local_mema_id) \
105 id = xrealloc(id, mema_id += 16); \ 117 id = xrealloc(id, local_mema_id += 16); \
106 id[id_len++] = c; } while(0) 118 id[id_len++] = c; } while(0)
107 119
108/* stupid C lexical analizator */ 120/* stupid C lexical analizator */
109static void c_lex(const char *fname, int flg_config_include) 121static void c_lex(const char *fname, long fsize)
110{ 122{
111 int c = EOF; /* stupid initialize */ 123 int c = L_EOF; /* stupid initialize */
112 int prev_state = EOF; 124 int prev_state = L_EOF;
113 int called; 125 int called;
114 int state; 126 int state;
115 int line; 127 int line;
116 static size_t mema_id; 128 char *id = id_s;
117 static char *id_s; 129 size_t local_mema_id = mema_id;
118 char *id;
119 size_t id_len = 0; /* stupid initialize */ 130 size_t id_len = 0; /* stupid initialize */
120 char *val = NULL; 131 char *val = NULL;
121 unsigned char *optr, *oend; 132 unsigned char *optr, *oend;
@@ -124,35 +135,20 @@ static void c_lex(const char *fname, int flg_config_include)
124 int fd; 135 int fd;
125 char *map; 136 char *map;
126 int mapsize; 137 int mapsize;
127 {
128 /* stolen from mkdep by Linus Torvalds */
129 int pagesizem1 = getpagesize() - 1;
130 struct stat st;
131 138
132 fd = open(fname, O_RDONLY); 139 fd = open(fname, O_RDONLY);
133 if(fd < 0) { 140 if(fd < 0) {
134 perror(fname); 141 perror(fname);
135 return; 142 return;
136 } 143 }
137 fstat(fd, &st); 144 mapsize = (fsize+pagesizem1) & ~pagesizem1;
138 if (st.st_size == 0) 145 map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
139 bb_error_d("%s is empty", fname); 146 if ((long) map == -1)
140 mapsize = st.st_size;
141 mapsize = (mapsize+pagesizem1) & ~pagesizem1;
142 map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
143 if ((long) map == -1)
144 bb_error_d("%s: mmap: %m", fname); 147 bb_error_d("%s: mmap: %m", fname);
145 148
146 /* hereinafter is my */ 149 optr = (unsigned char *)map;
147 optr = (unsigned char *)map; 150 oend = optr + fsize;
148 oend = optr + st.st_size;
149 }
150 151
151 if(id_s == NULL) {
152 /* fist allocate */
153 id_s = xmalloc(mema_id=128);
154 }
155 id = id_s;
156 line = 1; 152 line = 1;
157 called = state = S; 153 called = state = S;
158 154
@@ -163,10 +159,7 @@ static void c_lex(const char *fname, int flg_config_include)
163 if(state == LI) { 159 if(state == LI) {
164 parse_inc(id, fname); 160 parse_inc(id, fname);
165 } else { 161 } else {
166 /* 162 /* #define KEY "[VAL]" */
167 if(val[0] == '\0')
168 yy_error_d("expected value");
169 */
170 parse_conf_opt(id, val, (optr - start)); 163 parse_conf_opt(id, val, (optr - start));
171 } 164 }
172 state = S; 165 state = S;
@@ -180,7 +173,7 @@ static void c_lex(const char *fname, int flg_config_include)
180 while(c == ' ' || c == '\t') 173 while(c == ' ' || c == '\t')
181 getc1(); 174 getc1();
182 175
183 if(c == '\\') { 176 if(c == BS) {
184 getc1(); 177 getc1();
185 if(c == '\n') { 178 if(c == '\n') {
186 /* \\\n eat continued */ 179 /* \\\n eat continued */
@@ -189,49 +182,50 @@ static void c_lex(const char *fname, int flg_config_include)
189 continue; 182 continue;
190 } 183 }
191 ungetc1(); 184 ungetc1();
192 c = '\\'; 185 c = BS;
193 } 186 }
194 187
195 if(state == S) { 188 if(state == S) {
196 while(c <= ' ' && c != EOF) { 189 while(first_chars[c] == ANY) {
197 /* <S>[\000- ]+ */ 190 /* <S>unparsed */
198 if(c == '\n') 191 if(c == '\n')
199 line++; 192 line++;
200 getc1(); 193 getc1();
201 } 194 }
202 if(c == EOF) { 195 if(c == L_EOF) {
203 /* <S><<EOF>> */ 196 /* <S><<EOF>> */
197 id_s = id;
198 mema_id = local_mema_id;
204 munmap(map, mapsize); 199 munmap(map, mapsize);
205 close(fd); 200 close(fd);
206 return; 201 return;
207 } 202 }
208 if(c == '/') { 203 if(c == REM) {
209 /* <S>/ */ 204 /* <S>/ */
210 getc1(); 205 getc1(); /* eat <S>/ */
211 if(c == '/') { 206 if(c == REM) {
212 /* <S>"//"[^\n]* */ 207 /* <S>"//"[^\n]* */
213 do getc1(); while(c != '\n' && c != EOF); 208 do getc1(); while(c != '\n' && c != L_EOF);
214 } else if(c == '*') { 209 } else if(c == '*') {
215 /* <S>[/][*] */ 210 /* <S>[/][*] */
216 called = S; 211 called = S;
217 state = REM; 212 state = REM;
218 } 213 }
219 /* eat <S>/ */ 214 } else if(c == POUND) {
220 } else if(c == '#') { 215 /* <S># */
221 /* <S>\"|\'|# */
222 start = optr - 1; 216 start = optr - 1;
223 state = c; 217 state = c;
224 } else if(c == STR || c == CHR) { 218 } else if(c == STR || c == CHR) {
225 /* <S>\"|\'|# */ 219 /* <S>\"|\' */
226 val = NULL; 220 val = NULL;
227 called = S; 221 called = S;
228 state = c; 222 state = c;
229 } else if(ISALNUM(c)) { 223 } else if(c != BS) {
230 /* <S>[A-Z_a-z0-9] */ 224 /* <S>[A-Z_a-z0-9] */
231 225
232 /* trick for fast drop id 226 /* trick for fast drop id
233 if key with this first char undefined */ 227 if key with this first char undefined */
234 if(first_char_conf_opts[c] == 0) { 228 if(first_chars[c] == 0) {
235 /* skip <S>[A-Z_a-z0-9]+ */ 229 /* skip <S>[A-Z_a-z0-9]+ */
236 do getc1(); while(ISALNUM(c)); 230 do getc1(); while(ISALNUM(c));
237 } else { 231 } else {
@@ -242,11 +236,11 @@ static void c_lex(const char *fname, int flg_config_include)
242 getc1(); 236 getc1();
243 } while(ISALNUM(c)); 237 } while(ISALNUM(c));
244 put_id(0); 238 put_id(0);
245 find_already(key_top, id, CHECK_ONLY); 239 check_key(key_top, id);
246 } 240 }
247 } else { 241 } else {
248 /* <S>. */ 242 /* <S>\\ */
249 prev_state = ANY; 243 prev_state = c;
250 } 244 }
251 continue; 245 continue;
252 } 246 }
@@ -259,13 +253,13 @@ static void c_lex(const char *fname, int flg_config_include)
259 if(called != S) 253 if(called != S)
260 yy_error_d("unexpected newline"); 254 yy_error_d("unexpected newline");
261 line++; 255 line++;
262 } else if(c == EOF) 256 } else if(c == L_EOF)
263 yy_error_d("unexpected EOF"); 257 yy_error_d("unexpected EOF");
264 getc1(); 258 getc1();
265 } 259 }
266 /* <REM>[*] */ 260 /* <REM>[*] */
267 getc1(); 261 getc1();
268 if(c == '/') { 262 if(c == REM) {
269 /* <REM>[*][/] */ 263 /* <REM>[*][/] */
270 state = called; 264 state = called;
271 break; 265 break;
@@ -276,14 +270,14 @@ static void c_lex(const char *fname, int flg_config_include)
276 if(state == STR || state == CHR) { 270 if(state == STR || state == CHR) {
277 for(;;) { 271 for(;;) {
278 /* <STR,CHR>\n|<<EOF>> */ 272 /* <STR,CHR>\n|<<EOF>> */
279 if(c == '\n' || c == EOF) 273 if(c == '\n' || c == L_EOF)
280 yy_error_d("unterminating"); 274 yy_error_d("unterminating");
281 if(c == '\\') { 275 if(c == BS) {
282 /* <STR,CHR>\\ */ 276 /* <STR,CHR>\\ */
283 getc1(); 277 getc1();
284 if(c != '\\' && c != '\n' && c != state) { 278 if(c != BS && c != '\n' && c != state) {
285 /* another usage \ in str or char */ 279 /* another usage \ in str or char */
286 if(c == EOF) 280 if(c == L_EOF)
287 yy_error_d("unexpected EOF"); 281 yy_error_d("unexpected EOF");
288 if(val) 282 if(val)
289 put_id(c); 283 put_id(c);
@@ -298,7 +292,7 @@ static void c_lex(const char *fname, int flg_config_include)
298 } else if(c == state) { 292 } else if(c == state) {
299 /* <STR>\" or <CHR>\' */ 293 /* <STR>\" or <CHR>\' */
300 if(called == DV) 294 if(called == DV)
301 put_id(c); 295 put_id(c); /* #define KEY "VALUE"<- */
302 state = called; 296 state = called;
303 break; 297 break;
304 } else if(val) 298 } else if(val)
@@ -310,12 +304,12 @@ static void c_lex(const char *fname, int flg_config_include)
310 } 304 }
311 305
312 /* begin preprocessor states */ 306 /* begin preprocessor states */
313 if(c == EOF) 307 if(c == L_EOF)
314 yy_error_d("unexpected EOF"); 308 yy_error_d("unexpected EOF");
315 if(c == '/') { 309 if(c == REM) {
316 /* <#.*>/ */ 310 /* <#.*>/ */
317 getc1(); 311 getc1();
318 if(c == '/') 312 if(c == REM)
319 yy_error_d("detect // in preprocessor line"); 313 yy_error_d("detect // in preprocessor line");
320 if(c == '*') { 314 if(c == '*') {
321 /* <#.*>[/][*] */ 315 /* <#.*>[/][*] */
@@ -326,51 +320,55 @@ static void c_lex(const char *fname, int flg_config_include)
326 /* hmm, #.*[/] */ 320 /* hmm, #.*[/] */
327 yy_error_d("strange preprocessor line"); 321 yy_error_d("strange preprocessor line");
328 } 322 }
329 if(state == '#') { 323 if(state == POUND) {
324 if(c != 'd' && c != 'u' && c != 'i') {
325 while(ISALNUM(c))
326 getc1();
327 state = S;
328 } else {
330 static const char * const preproc[] = { 329 static const char * const preproc[] = {
331 "define", "undef", "include", "" 330 "define", "undef", "include", ""
332 }; 331 };
333 const char * const *str_type; 332 const char * const *str_type;
334 333
335 id_len = 0; 334 id_len = 0;
336 while(ISALNUM(c)) { 335 do { put_id(c); getc1(); } while(ISALNUM(c));
337 put_id(c);
338 getc1();
339 }
340 put_id(0); 336 put_id(0);
341 for(str_type = preproc; (state = **str_type); str_type++) { 337 for(str_type = preproc; (state = **str_type); str_type++) {
342 if(*id == state && strcmp(id, *str_type) == 0) 338 if(*id == state && strcmp(id, *str_type) == 0)
343 break; 339 break;
344 } 340 }
345 /* to S if another #directive */ 341 /* to S if another #directive */
346 ungetc1();
347 id_len = 0; /* common for save */ 342 id_len = 0; /* common for save */
348 continue; 343 }
344 ungetc1();
345 continue;
349 } 346 }
350 if(state == I) { 347 if(state == I) {
351 if(c == STR) { 348 if(c == STR) {
352 /* <I>\" */ 349 /* <I>\" */
353 val = id; 350 val = id;
354 state = STR;
355 called = LI; 351 called = LI;
356 continue; 352 state = STR;
353 } else {
354 /* another (may be wrong) #include ... */
355 ungetc1();
356 state = S;
357 } 357 }
358 /* another (may be wrong) #include ... */
359 ungetc1();
360 state = S;
361 continue; 358 continue;
362 } 359 }
363 if(state == D || state == U) { 360 if(state == D || state == U) {
364 while(ISALNUM(c)) { 361 if(configs == NULL) {
365 if(flg_config_include) { 362 /* ignore depend with #define or #undef KEY */
366 /* save KEY from #"define"|"undef" ... */ 363 while(ISALNUM(c))
367 put_id(c); 364 getc1();
368 }
369 getc1();
370 }
371 if(!flg_config_include) {
372 state = S; 365 state = S;
373 } else { 366 } else {
367 /* save KEY from #"define"|"undef" ... */
368 while(ISALNUM(c)) {
369 put_id(c);
370 getc1();
371 }
374 if(!id_len) 372 if(!id_len)
375 yy_error_d("expected identificator"); 373 yy_error_d("expected identificator");
376 put_id(0); 374 put_id(0);
@@ -386,7 +384,7 @@ static void c_lex(const char *fname, int flg_config_include)
386 continue; 384 continue;
387 } 385 }
388 if(state == DK) { 386 if(state == DK) {
389 /* #define (config mode) */ 387 /* #define KEY[ ] (config mode) */
390 val = id + id_len; 388 val = id + id_len;
391 if(c == STR || c == CHR) { 389 if(c == STR || c == CHR) {
392 /* define KEY "... or define KEY '... */ 390 /* define KEY "... or define KEY '... */
@@ -396,6 +394,7 @@ static void c_lex(const char *fname, int flg_config_include)
396 continue; 394 continue;
397 } 395 }
398 while(ISALNUM(c)) { 396 while(ISALNUM(c)) {
397 /* VALUE */
399 put_id(c); 398 put_id(c);
400 getc1(); 399 getc1();
401 } 400 }
@@ -410,43 +409,51 @@ static void c_lex(const char *fname, int flg_config_include)
410static void show_usage(void) __attribute__ ((noreturn)); 409static void show_usage(void) __attribute__ ((noreturn));
411static void show_usage(void) 410static void show_usage(void)
412{ 411{
413 bb_error_d("Usage: [-I local_include_path] [-dw] " 412 bb_error_d("Usage: [-I local_include_paths] [-dw] "
414 "[-k path_for_store_keys] [-s skip_file]"); 413 "[-k path_for_store_keys] [-s skip_file] [dirs]");
415} 414}
416 415
417static const char *kp; 416static const char *kp;
417static size_t kp_len;
418static llist_t *Iop; 418static llist_t *Iop;
419static bb_key_t *Ifound; 419static bb_key_t *Ifound;
420static int noiwarning; 420static int noiwarning;
421static llist_t *configs;
422 421
423static bb_key_t *find_already(bb_key_t *k, const char *nk, int flg_save_new) 422static bb_key_t *check_key(bb_key_t *k, const char *nk)
424{ 423{
425 bb_key_t *cur; 424 bb_key_t *cur;
426 425
427 for(cur = k; cur; cur = cur->next) { 426 for(cur = k; cur; cur = cur->next) {
428 if(strcmp(cur->keyname, nk) == 0) { 427 if(strcmp(cur->keyname, nk) == 0) {
429 cur->checked = 1; 428 cur->checked = 1;
430 return NULL; 429 return cur;
431 }
432 } 430 }
433 if(flg_save_new == CHECK_ONLY) 431 }
434 return NULL; 432 return NULL;
435 cur = xmalloc(sizeof(bb_key_t)); 433}
436 cur->keyname = bb_xstrdup(nk); 434
435static bb_key_t *make_new_key(bb_key_t *k, const char *nk)
436{
437 bb_key_t *cur;
438 size_t nk_size;
439
440 nk_size = strlen(nk) + 1;
441 cur = xmalloc(sizeof(bb_key_t) + nk_size);
442 cur->keyname = memcpy(cur + 1, nk, nk_size);
437 cur->checked = 1; 443 cur->checked = 1;
438 cur->next = k; 444 cur->next = k;
439 return cur; 445 return cur;
440} 446}
441 447
442static int store_include_fullpath(char *p_i, bb_key_t *li) 448static inline char *store_include_fullpath(char *p_i, bb_key_t *li)
443{ 449{
444 struct stat st; 450 struct stat st;
445 int ok = 0; 451 char *ok;
446 452
447 if(stat(p_i, &st) == 0) { 453 if(stat(p_i, &st) == 0) {
448 li->stored_path = bb_simplify_path(p_i); 454 ok = li->stored_path = bb_simplify_path(p_i);
449 ok = 1; 455 } else {
456 ok = NULL;
450 } 457 }
451 free(p_i); 458 free(p_i);
452 return ok; 459 return ok;
@@ -458,9 +465,11 @@ static void parse_inc(const char *include, const char *fname)
458 char *p_i; 465 char *p_i;
459 llist_t *lo; 466 llist_t *lo;
460 467
461 if((li = find_already(Ifound, include, MAKE_NEW)) == NULL) 468 li = check_key(Ifound, include);
469 if(li)
462 return; 470 return;
463 Ifound = li; 471 Ifound = li = make_new_key(Ifound, include);
472
464 if(include[0] != '/') { 473 if(include[0] != '/') {
465 /* relative */ 474 /* relative */
466 int w; 475 int w;
@@ -490,9 +499,10 @@ static void parse_inc(const char *include, const char *fname)
490 499
491static void parse_conf_opt(char *opt, const char *val, size_t recordsz) 500static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
492{ 501{
493 bb_key_t *cur = find_already(key_top, opt, MAKE_NEW); 502 bb_key_t *cur;
494 503
495 if(cur != NULL) { 504 cur = check_key(key_top, opt);
505 if(cur == NULL) {
496 /* new key, check old key if present after previous usage */ 506 /* new key, check old key if present after previous usage */
497 char *s, *p; 507 char *s, *p;
498 struct stat st; 508 struct stat st;
@@ -501,6 +511,9 @@ static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
501 static char *record_buf; 511 static char *record_buf;
502 static char *r_cmp; 512 static char *r_cmp;
503 static size_t r_sz; 513 static size_t r_sz;
514 ssize_t rw_ret;
515
516 cur = make_new_key(key_top, opt);
504 517
505 recordsz += 2; /* \n\0 */ 518 recordsz += 2; /* \n\0 */
506 if(recordsz > r_sz) { 519 if(recordsz > r_sz) {
@@ -509,12 +522,24 @@ static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
509 } 522 }
510 s = record_buf; 523 s = record_buf;
511 /* may be short count " " */ 524 /* may be short count " " */
512 if(val) 525 if(val) {
513 recordsz = sprintf(s, "#define %s%s%s\n", opt, (*val ? " " : ""), val); 526 if(*val == '\0') {
514 else 527 cur->value = "";
528 recordsz = sprintf(s, "#define %s\n", opt);
529 } else {
530 cur->value = bb_xstrdup(val);
531 recordsz = sprintf(s, "#define %s %s\n", opt, val);
532 }
533 } else {
534 cur->value = NULL;
515 recordsz = sprintf(s, "#undef %s\n", opt); 535 recordsz = sprintf(s, "#undef %s\n", opt);
516 first_char_conf_opts[((int)((unsigned char)(*opt)))] = *opt; 536 }
517 /* key converting [A-Z] -> [a-z] */ 537 /* size_t -> ssize_t :( */
538 rw_ret = (ssize_t)recordsz;
539 /* trick, save first char KEY for do fast identify id */
540 first_chars[(int)*opt] = *opt;
541
542 /* key converting [A-Z_] -> [a-z/] */
518 for(p = opt; *p; p++) { 543 for(p = opt; *p; p++) {
519 if(*p >= 'A' && *p <= 'Z') 544 if(*p >= 'A' && *p <= 'Z')
520 *p = *p - 'A' + 'a'; 545 *p = *p - 'A' + 'a';
@@ -524,6 +549,7 @@ static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
524 p = bb_asprint("%s/%s.h", kp, opt); 549 p = bb_asprint("%s/%s.h", kp, opt);
525 cur->stored_path = opt = p; 550 cur->stored_path = opt = p;
526 if(stat(opt, &st)) { 551 if(stat(opt, &st)) {
552 p += kp_len;
527 while(*++p) { 553 while(*++p) {
528 /* Auto-create directories. */ 554 /* Auto-create directories. */
529 if (*p == '/') { 555 if (*p == '/') {
@@ -535,9 +561,9 @@ static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
535 } 561 }
536 } else { 562 } else {
537 /* found */ 563 /* found */
538 if(st.st_size == recordsz) { 564 if(st.st_size == (off_t)recordsz) {
539 fd = open(opt, O_RDONLY); 565 fd = open(opt, O_RDONLY);
540 if(fd < 0 || read(fd, r_cmp, recordsz) != recordsz) 566 if(fd < 0 || read(fd, r_cmp, recordsz) < rw_ret)
541 bb_error_d("%s: %m", opt); 567 bb_error_d("%s: %m", opt);
542 close(fd); 568 close(fd);
543 cmp_ok = memcmp(s, r_cmp, recordsz) == 0; 569 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)
545 } 571 }
546 if(!cmp_ok) { 572 if(!cmp_ok) {
547 fd = open(opt, O_WRONLY|O_CREAT|O_TRUNC, 0644); 573 fd = open(opt, O_WRONLY|O_CREAT|O_TRUNC, 0644);
548 if(fd < 0 || write(fd, s, recordsz) != recordsz) 574 if(fd < 0 || write(fd, s, recordsz) < rw_ret)
549 bb_error_d("%s: %m", opt); 575 bb_error_d("%s: %m", opt);
550 close(fd); 576 close(fd);
551 } 577 }
552 /* store only */
553 cur->checked = 0;
554 if(val) {
555 if(*val == '\0') {
556 cur->value = "";
557 } else {
558 cur->value = bb_xstrdup(val);
559 }
560 } else {
561 cur->value = NULL;
562 }
563 key_top = cur; 578 key_top = cur;
564 } else { 579 } else {
565 /* present already */ 580 /* present already */
566 for(cur = key_top; cur; cur = cur->next) { 581 if((cur->value == NULL && val != NULL) ||
567 if(strcmp(cur->keyname, opt) == 0) { 582 (cur->value != NULL && val == NULL) ||
568 cur->checked = 0; 583 (cur->value != NULL && val != NULL && strcmp(cur->value, val)))
569 if(cur->value == NULL && val == NULL) 584 fprintf(stderr, "Warning: redefined %s\n", opt);
570 return;
571 if((cur->value == NULL && val != NULL) ||
572 (cur->value != NULL && val == NULL) ||
573 strcmp(cur->value, val))
574 fprintf(stderr, "Warning: redefined %s\n", opt);
575 return;
576 }
577 }
578 } 585 }
586 /* store only */
587 cur->checked = 0;
579} 588}
580 589
581static int show_dep(int first, bb_key_t *k, const char *a) 590static int show_dep(int first, bb_key_t *k, const char *name)
582{ 591{
583 bb_key_t *cur; 592 bb_key_t *cur;
584 593
585 for(cur = k; cur; cur = cur->next) { 594 for(cur = k; cur; cur = cur->next) {
586 if(cur->checked && cur->stored_path) { 595 if(cur->checked && cur->stored_path) {
587 if(first) { 596 if(first) {
588 const char *ext; 597 printf("\n%s:", name);
589
590 if(*a == '.' && a[1] == '/')
591 a += 2;
592 ext = strrchr(a, '.');
593 if(ext && ext[1] == 'c' && ext[2] == '\0') {
594 /* *.c -> *.o */
595 printf("\n%.*s.o:", (ext - a), a);
596 } else {
597 printf("\n%s:", a);
598 }
599 first = 0; 598 first = 0;
600 } else { 599 } else {
601 printf(" \\\n "); 600 printf(" \\\n ");
@@ -608,50 +607,56 @@ static int show_dep(int first, bb_key_t *k, const char *a)
608} 607}
609 608
610static llist_t *files; 609static llist_t *files;
610static struct stat st_kp;
611
612static char *dir_and_entry;
611 613
612static llist_t *filter_chd(const char *fe, const char *p, llist_t *pdirs) 614static char *
615filter_chd(const char *fe, const char *p, size_t dirlen)
613{ 616{
614 struct stat st; 617 struct stat st;
615 char *fp; 618 char *fp;
616 char *afp; 619 char *afp;
617 llist_t *cfl; 620 llist_t *cfl;
618 static struct stat st_kp; 621 file_list_t *f;
622 size_t df_sz;
623 static size_t dir_and_entry_sz;
619 624
620 if (*fe == '.') 625 if (*fe == '.')
621 return NULL; 626 return NULL;
622 fp = bb_asprint("%s/%s", p, fe); 627
628 df_sz = dirlen + strlen(fe) + 2; /* dir/file\0 */
629 if(df_sz > dir_and_entry_sz)
630 dir_and_entry = xrealloc(dir_and_entry, dir_and_entry_sz = df_sz);
631 fp = dir_and_entry;
632 sprintf(fp, "%s/%s", p, fe);
633
623 if(stat(fp, &st)) { 634 if(stat(fp, &st)) {
624 fprintf(stderr, "Warning: stat(%s): %m", fp); 635 fprintf(stderr, "Warning: stat(%s): %m", fp);
625 free(fp);
626 return NULL; 636 return NULL;
627 } 637 }
628 if(S_ISREG(st.st_mode)) { 638 if(S_ISREG(st.st_mode)) {
629 const char *e = strrchr(fe, '.'); 639 afp = fp + df_sz - 3;
630 640 if(*afp++ != '.' || (*afp != 'c' && *afp != 'h')) {
631 if(e == NULL || !((e[1]=='c' || e[1]=='h') && e[2]=='\0')) {
632 /* direntry is regular file, but is not *.[ch] */ 641 /* direntry is regular file, but is not *.[ch] */
633 free(fp);
634 return NULL; 642 return NULL;
635 } 643 }
636 } else { 644 if (st.st_size == 0) {
637 if(st_kp.st_ino == 0) { 645 fprintf(stderr, "Warning: %s is empty\n", fp);
638 /* first call */ 646 return NULL;
639 if(stat(kp, &st_kp))
640 bb_error_d("stat(%s): %m", kp);
641 if(!S_ISDIR(st_kp.st_mode))
642 bb_error_d("%s is not directory", kp);
643 } 647 }
648 } else {
644 if(S_ISDIR(st.st_mode)) { 649 if(S_ISDIR(st.st_mode)) {
645 if (st.st_dev == st_kp.st_dev && st.st_ino == st_kp.st_ino) { 650 if (st.st_dev == st_kp.st_dev && st.st_ino == st_kp.st_ino) {
646 /* is autogenerated to kp/key* by previous usage */
647 free(fp);
648 /* drop scan kp/ directory */ 651 /* drop scan kp/ directory */
649 return NULL; 652 return NULL;
650 } 653 }
651 return llist_add_to(pdirs, fp); 654 /* buff is returned, begin of zero allocate */
655 dir_and_entry = NULL;
656 dir_and_entry_sz = 0;
657 return fp;
652 } 658 }
653 /* hmm, is device! */ 659 /* hmm, is device! */
654 free(fp);
655 return NULL; 660 return NULL;
656 } 661 }
657 afp = bb_simplify_path(fp); 662 afp = bb_simplify_path(fp);
@@ -659,16 +664,18 @@ static llist_t *filter_chd(const char *fe, const char *p, llist_t *pdirs)
659 if(cfl->data && strcmp(cfl->data, afp) == 0) { 664 if(cfl->data && strcmp(cfl->data, afp) == 0) {
660 /* parse configs.h */ 665 /* parse configs.h */
661 free(afp); 666 free(afp);
662 c_lex(fp, 1); 667 c_lex(fp, st.st_size);
663 free(fp);
664 free(cfl->data); 668 free(cfl->data);
665 cfl->data = NULL; 669 cfl->data = NULL;
666 return NULL; 670 return NULL;
667 } 671 }
668 } 672 }
669 free(fp);
670 /* direntry is *.[ch] regular file */ 673 /* direntry is *.[ch] regular file */
671 files = llist_add_to(files, afp); 674 f = xmalloc(sizeof(file_list_t));
675 f->name = afp;
676 f->ext = strrchr(afp, '.') + 1;
677 f->size = st.st_size;
678 files = llist_add_to(files, (char *)f);
672 return NULL; 679 return NULL;
673} 680}
674 681
@@ -679,6 +686,7 @@ static void scan_dir_find_ch_files(char *p)
679 llist_t *d; 686 llist_t *d;
680 struct dirent *de; 687 struct dirent *de;
681 DIR *dir; 688 DIR *dir;
689 size_t dirlen;
682 690
683 dirs = llist_add_to(NULL, p); 691 dirs = llist_add_to(NULL, p);
684 /* emulate recursive */ 692 /* emulate recursive */
@@ -688,10 +696,12 @@ static void scan_dir_find_ch_files(char *p)
688 dir = opendir(dirs->data); 696 dir = opendir(dirs->data);
689 if (dir == NULL) 697 if (dir == NULL)
690 fprintf(stderr, "Warning: opendir(%s): %m", dirs->data); 698 fprintf(stderr, "Warning: opendir(%s): %m", dirs->data);
699 dirlen = strlen(dirs->data);
691 while ((de = readdir(dir)) != NULL) { 700 while ((de = readdir(dir)) != NULL) {
692 d = filter_chd(de->d_name, dirs->data, d_add); 701 char *found_dir = filter_chd(de->d_name, dirs->data, dirlen);
693 if(d) 702
694 d_add = d; 703 if(found_dir)
704 d_add = llist_add_to(d_add, found_dir);
695 } 705 }
696 closedir(dir); 706 closedir(dir);
697 if(dirs->data != p) 707 if(dirs->data != p)
@@ -702,15 +712,10 @@ static void scan_dir_find_ch_files(char *p)
702 } 712 }
703 dirs = d_add; 713 dirs = d_add;
704 } 714 }
705 for(d = configs; d; d = d->link) {
706 if(d->data) {
707 /* configs.h placed outsize of "." */
708 c_lex(d->data, 1);
709 free(d->data);
710 }
711 }
712} 715}
713 716
717static char *pwd;
718
714int main(int argc, char **argv) 719int main(int argc, char **argv)
715{ 720{
716 int generate_dep = 1; 721 int generate_dep = 1;
@@ -718,6 +723,22 @@ int main(int argc, char **argv)
718 int i; 723 int i;
719 llist_t *fl; 724 llist_t *fl;
720 725
726 {
727 /* for bb_simplify_path */
728 /* libbb xgetcwd(), this program have not chdir() */
729 unsigned path_max = 512;
730
731 s = xmalloc (path_max);
732#define PATH_INCR 32
733 while (getcwd (s, path_max) == NULL) {
734 if(errno != ERANGE)
735 bb_error_d("getcwd: %m");
736 path_max += PATH_INCR;
737 s = xrealloc (s, path_max);
738 }
739 pwd = s;
740 }
741
721 while ((i = getopt(argc, argv, "I:c:dk:w")) > 0) { 742 while ((i = getopt(argc, argv, "I:c:dk:w")) > 0) {
722 switch(i) { 743 switch(i) {
723 case 'I': 744 case 'I':
@@ -742,9 +763,6 @@ int main(int argc, char **argv)
742 show_usage(); 763 show_usage();
743 } 764 }
744 } 765 }
745 if(argc > optind)
746 show_usage();
747
748 /* defaults */ 766 /* defaults */
749 if(kp == NULL) 767 if(kp == NULL)
750 kp = bb_simplify_path(INCLUDE_CONFIG_PATH); 768 kp = bb_simplify_path(INCLUDE_CONFIG_PATH);
@@ -754,13 +772,57 @@ int main(int argc, char **argv)
754 s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH); 772 s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH);
755 configs = llist_add_to(configs, s); 773 configs = llist_add_to(configs, s);
756 } 774 }
775 /* globals initialize */
776 /* for c_lex */
777 pagesizem1 = getpagesize() - 1;
778 id_s = xmalloc(mema_id);
779 for(i = 0; i < 256; i++) {
780 /* set unparsed chars for speed up of parser */
781 if(!ISALNUM(i) && i != CHR && i != STR &&
782 i != POUND && i != REM && i != BS)
783 first_chars[i] = ANY;
784 }
785 first_chars[i] = '-'; /* L_EOF */
786
787 kp_len = strlen(kp);
788 if(stat(kp, &st_kp))
789 bb_error_d("stat(%s): %m", kp);
790 if(!S_ISDIR(st_kp.st_mode))
791 bb_error_d("%s is not directory", kp);
792
793 /* main loops */
794 argv += optind;
795 if(*argv) {
796 while(*argv)
797 scan_dir_find_ch_files(*argv++);
798 } else {
799 scan_dir_find_ch_files(".");
800 }
801
802 for(fl = configs; fl; fl = fl->link) {
803 if(fl->data) {
804 /* configs.h placed outsize of scanned dirs or not "*.ch" */
805 struct stat st;
806
807 if(stat(fl->data, &st))
808 bb_error_d("stat(%s): %m", fl->data);
809 c_lex(fl->data, st.st_size);
810 free(fl->data);
811 }
812 }
813 free(configs);
814 configs = NULL; /* flag read config --> parse sourses mode */
757 815
758 scan_dir_find_ch_files(".");
759 for(fl = files; fl; fl = fl->link) { 816 for(fl = files; fl; fl = fl->link) {
760 c_lex(fl->data, 0); 817 file_list_t *t = (file_list_t *)(fl->data);
818 c_lex(t->name, t->size);
761 if(generate_dep) { 819 if(generate_dep) {
762 i = show_dep(1, Ifound, fl->data); 820 if(t->ext[0] == 'c') {
763 i = show_dep(i, key_top, fl->data); 821 /* *.c -> *.o */
822 t->ext[0] = 'o';
823 }
824 i = show_dep(1, Ifound, t->name);
825 i = show_dep(i, key_top, t->name);
764 if(i == 0) 826 if(i == 0)
765 putchar('\n'); 827 putchar('\n');
766 } 828 }
@@ -768,6 +830,7 @@ int main(int argc, char **argv)
768 return 0; 830 return 0;
769} 831}
770 832
833/* partial and simplify libbb routine */
771static void bb_error_d(const char *s, ...) 834static void bb_error_d(const char *s, ...)
772{ 835{
773 va_list p; 836 va_list p;
@@ -836,24 +899,10 @@ static char *bb_simplify_path(const char *path)
836 char *s, *start, *p; 899 char *s, *start, *p;
837 900
838 if (path[0] == '/') 901 if (path[0] == '/')
839 start = bb_xstrdup(path); 902 start = bb_xstrdup(path);
840 else { 903 else {
841 static char *pwd; 904 /* is not libbb, but this program have not chdir() */
842 905 start = bb_asprint("%s/%s", pwd, path);
843 if(pwd == NULL) {
844 /* is not libbb, but this program have not chdir() */
845 unsigned path_max = 512;
846 char *cwd = xmalloc (path_max);
847#define PATH_INCR 32
848 while (getcwd (cwd, path_max) == NULL) {
849 if(errno != ERANGE)
850 bb_error_d("getcwd: %m");
851 path_max += PATH_INCR;
852 cwd = xrealloc (cwd, path_max);
853 }
854 pwd = cwd;
855 }
856 start = bb_asprint("%s/%s", pwd, path);
857 } 906 }
858 p = s = start; 907 p = s = start;
859 908