summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
author"Vladimir N. Oleynik" <dzo@simtreas.ru>2005-10-10 11:35:17 +0000
committer"Vladimir N. Oleynik" <dzo@simtreas.ru>2005-10-10 11:35:17 +0000
commit083d3f49c2c0fec0bd8b5b0bec875d67748c612e (patch)
treebb326553f70f3bebe7ff3ed3cf1d57dcc8a5e8ab /scripts
parentff9f2f6fbae538d27197e7e357da187031ef33df (diff)
downloadbusybox-w32-083d3f49c2c0fec0bd8b5b0bec875d67748c612e.tar.gz
busybox-w32-083d3f49c2c0fec0bd8b5b0bec875d67748c612e.tar.bz2
busybox-w32-083d3f49c2c0fec0bd8b5b0bec875d67748c612e.zip
bb_mkdep: Rewroted. removed problem "include name must uniq", speed up * 3.
e2fsprogs: remove confuse bb_mkdep. Use internal e2fsprogs includes only. other: remove confuse bb_mkdep.
Diffstat (limited to 'scripts')
-rw-r--r--scripts/bb_mkdep.c811
1 files changed, 415 insertions, 396 deletions
diff --git a/scripts/bb_mkdep.c b/scripts/bb_mkdep.c
index 76db960fd..758b78cb9 100644
--- a/scripts/bb_mkdep.c
+++ b/scripts/bb_mkdep.c
@@ -1,9 +1,20 @@
1/* 1/*
2 * Another fast dependencies generator for Makefiles, Version 2.5 2 * Another fast dependencies generator for Makefiles, Version 3.0
3 * 3 *
4 * Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru> 4 * Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru>
5 *
5 * mmaping file may be originally by Linus Torvalds. 6 * mmaping file may be originally by Linus Torvalds.
6 * 7 *
8 * bb_simplify_path()
9 * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org>
10 *
11 * xmalloc() bb_xstrdup() bb_error_d():
12 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
13 *
14 * llist routine
15 * Copyright (C) 2003 Glenn McGrath
16 * Copyright (C) Vladimir Oleynik <dzo@simtreas.ru>
17 *
7 * (c) 2005 Bernhard Fischer: 18 * (c) 2005 Bernhard Fischer:
8 * - commentary typos, 19 * - commentary typos,
9 * - move "memory exhausted" into msg_enomem, 20 * - move "memory exhausted" into msg_enomem,
@@ -11,14 +22,13 @@
11 * 22 *
12 * This program does: 23 * This program does:
13 * 1) find #define KEY VALUE or #undef KEY from include/config.h 24 * 1) find #define KEY VALUE or #undef KEY from include/config.h
14 * 2) save include/config/key*.h if changed after previous usage 25 * 2) recursive find and scan *.[ch] files, but skips scan of include/config/
15 * 3) recursive find and scan *.[ch] files, but skips scan of include/config/ 26 * 3) find #include "*.h" and KEYs using, if not as #define and #undef
16 * 4) find #include "*.h" and KEYs using, if not as #define and #undef 27 * 4) generate dependencies to stdout
17 * 5) generate dependencies to stdout
18 * pwd/file.o: include/config/key*.h found_include_*.h 28 * pwd/file.o: include/config/key*.h found_include_*.h
19 * path/inc.h: include/config/key*.h found_included_include_*.h 29 * path/inc.h: include/config/key*.h found_included_include_*.h
30 * 5) save include/config/key*.h if changed after previous usage
20 * This program does not generate dependencies for #include <...> 31 * This program does not generate dependencies for #include <...>
21 * BUG: all includes name must unique
22 */ 32 */
23 33
24#define LOCAL_INCLUDE_PATH "include" 34#define LOCAL_INCLUDE_PATH "include"
@@ -51,62 +61,100 @@
51#include <unistd.h> 61#include <unistd.h>
52#include <errno.h> 62#include <errno.h>
53#include <fcntl.h> 63#include <fcntl.h>
64#include <limits.h>
54 65
55 66
56typedef struct BB_KEYS {
57 char *keyname;
58 size_t key_sz;
59 const char *value;
60 char *stored_path;
61 char *checked;
62 struct BB_KEYS *next;
63} bb_key_t;
64
65static bb_key_t *check_key(bb_key_t *k, const char *nk, size_t key_sz);
66static bb_key_t *make_new_key(bb_key_t *k, const char *nk, size_t key_sz);
67
68/* partial and simplified libbb routine */ 67/* partial and simplified libbb routine */
69static void bb_error_d(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))); 68static void bb_error_d(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
70static char * bb_asprint(const char *format, ...) __attribute__ ((format (printf, 1, 2))); 69static char * bb_asprint(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
70static char *bb_simplify_path(const char *path);
71 71
72/* stolen from libbb as is */ 72/* stolen from libbb as is */
73typedef struct llist_s { 73typedef struct llist_s {
74 char *data; 74 char *data;
75 struct llist_s *link; 75 struct llist_s *link;
76} llist_t; 76} llist_t;
77static void *xrealloc(void *p, size_t size); 77
78static void *xmalloc(size_t size);
79static char *bb_xstrdup(const char *s);
80static char *bb_simplify_path(const char *path);
81/* error messages */
82static const char msg_enomem[] = "memory exhausted"; 78static const char msg_enomem[] = "memory exhausted";
83 79
84/* for lexical analyser */ 80/* inline realization for fast works */
85static bb_key_t *key_top; 81static inline void *xmalloc(size_t size)
86static llist_t *configs; 82{
83 void *p = malloc(size);
87 84
88static int mode; 85 if(p == NULL)
89#define CONFIG_MODE 0 86 bb_error_d(msg_enomem);
90#define SOURCES_MODE 1 87 return p;
88}
89
90static inline char *bb_xstrdup(const char *s)
91{
92 char *r = strdup(s);
91 93
92static void parse_inc(const char *include, const char *fname, size_t key_sz); 94 if(r == NULL)
93static void parse_conf_opt(const char *opt, const char *val, 95 bb_error_d(msg_enomem);
94 size_t rsz, size_t key_sz); 96 return r;
97}
98
99
100static int dontgenerate_dep; /* flag -d usaged */
101static int noiwarning; /* flag -w usaged */
102static llist_t *configs; /* list of -c usaged and them stat() after parsed */
103static llist_t *Iop; /* list of -I include usaged */
104
105static char *pwd; /* current work directory */
106static size_t replace; /* replace current work derectory to build dir */
107
108static const char *kp; /* KEY path, argument of -k usaged */
109static size_t kp_len;
110static struct stat st_kp; /* stat(kp) */
111
112typedef struct BB_KEYS {
113 char *keyname;
114 size_t key_sz;
115 const char *value;
116 const char *checked;
117 char *stored_path;
118 const char *src_have_this_key;
119 struct BB_KEYS *next;
120} bb_key_t;
121
122static bb_key_t *key_top; /* list of found KEYs */
123static bb_key_t *Ifound; /* list of parsed includes */
124
125
126static void parse_conf_opt(const char *opt, const char *val, size_t key_sz);
127static void parse_inc(const char *include, const char *fname);
128
129static inline bb_key_t *check_key(bb_key_t *k, const char *nk, size_t key_sz)
130{
131 bb_key_t *cur;
132
133 for(cur = k; cur; cur = cur->next) {
134 if(key_sz == cur->key_sz && memcmp(cur->keyname, nk, key_sz) == 0) {
135 cur->checked = cur->stored_path;
136 return cur;
137 }
138 }
139 return NULL;
140}
141
142/* for lexical analyser */
143static int pagesizem1; /* padding mask = getpagesize() - 1 */
95 144
96/* for speed tricks */ 145/* for speed tricks */
97static char first_chars[257]; /* + L_EOF */ 146static char first_chars[1+UCHAR_MAX]; /* + L_EOF */
98static char isalnums[257]; /* + L_EOF */ 147static char isalnums[1+UCHAR_MAX]; /* + L_EOF */
99/* trick for fast find "define", "include", "undef" */ 148/* trick for fast find "define", "include", "undef" */
100static char first_chars_diu[256] = { 149static const char first_chars_diu[UCHAR_MAX] = {
101 [(int)'d'] = (char)5, /* strlen("define") - 1; */ 150 [(int)'d'] = (char)5, /* strlen("define") - 1; */
102 [(int)'i'] = (char)6, /* strlen("include") - 1; */ 151 [(int)'i'] = (char)6, /* strlen("include") - 1; */
103 [(int)'u'] = (char)4, /* strlen("undef") - 1; */ 152 [(int)'u'] = (char)4, /* strlen("undef") - 1; */
104}; 153};
105 154
106static int pagesizem1; 155#define CONFIG_MODE 0
107static size_t mema_id = 128; /* first allocated for id */ 156#define SOURCES_MODE 1
108static char *id_s; 157static int mode;
109
110 158
111#define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s) 159#define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s)
112 160
@@ -117,44 +165,40 @@ static char *id_s;
117#define REM '/' /* block comment */ 165#define REM '/' /* block comment */
118#define BS '\\' /* back slash */ 166#define BS '\\' /* back slash */
119#define POUND '#' /* # */ 167#define POUND '#' /* # */
120#define I 'i' /* #include preprocessor's directive */ 168#define D '5' /* #define preprocessor's directive */
121#define D 'd' /* #define preprocessor's directive */ 169#define I '6' /* #include preprocessor's directive */
122#define U 'u' /* #undef preprocessor's directive */ 170#define U '4' /* #undef preprocessor's directive */
123#define LI 'I' /* #include "... */
124#define DK 'K' /* #define KEY... (config mode) */ 171#define DK 'K' /* #define KEY... (config mode) */
125#define DV 'V' /* #define KEY "VALUE or #define KEY 'VALUE */
126#define NLC 'n' /* \ and \n */
127#define ANY '*' /* any unparsed chars */ 172#define ANY '*' /* any unparsed chars */
128 173
129#define L_EOF 256
130/* [A-Z_a-z] */ 174/* [A-Z_a-z] */
131#define ID(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') 175#define ID(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_')
132/* [A-Z_a-z0-9] */ 176/* [A-Z_a-z0-9] */
133#define ISALNUM(c) (ID(c) || (c >= '0' && c <= '9')) 177#define ISALNUM(c) (ID(c) || (c >= '0' && c <= '9'))
134 178
135#define getc1() do { c = (optr >= oend) ? L_EOF : *optr++; } while(0) 179#define L_EOF (1+UCHAR_MAX)
136#define ungetc1() optr--
137 180
138#define put_id(c) do { if(id_len == local_mema_id) \ 181#define getc0() do { c = (optr >= oend) ? L_EOF : *optr++; } while(0)
139 id = xrealloc(id, local_mema_id += 16); \ 182
140 id[id_len++] = c; } while(0) 183#define getc1() do { getc0(); if(c == BS) { getc0(); \
184 if(c == '\n') { line++; continue; } \
185 else { optr--; c = BS; } \
186 } break; } while(1)
187
188static char id_s[4096];
189#define put_id(ic) do { if(id_len == sizeof(id_s)) goto too_long; \
190 id[id_len++] = ic; } while(0)
141 191
142 192
143/* stupid C lexical analyser */ 193/* stupid C lexical analyser */
144static void c_lex(const char *fname, long fsize) 194static void c_lex(const char *fname, long fsize)
145{ 195{
146 int c = L_EOF; /* stupid initialize */ 196 int c;
147 int prev_state = L_EOF;
148 int called;
149 int state; 197 int state;
150 int line; 198 int line;
151 char *id = id_s; 199 char *id = id_s;
152 size_t local_mema_id = mema_id;
153 size_t id_len = 0; /* stupid initialize */ 200 size_t id_len = 0; /* stupid initialize */
154 char *val = NULL;
155 unsigned char *optr, *oend; 201 unsigned char *optr, *oend;
156 unsigned char *start = NULL; /* stupid initialize */
157 size_t opt_len = 0; /* stupid initialize */
158 202
159 int fd; 203 int fd;
160 char *map; 204 char *map;
@@ -178,30 +222,15 @@ static void c_lex(const char *fname, long fsize)
178 oend = optr + fsize; 222 oend = optr + fsize;
179 223
180 line = 1; 224 line = 1;
181 called = state = S; 225 state = S;
182 226
183 for(;;) { 227 for(;;) {
184 if(prev_state != state) { 228 getc1();
185 prev_state = state; 229 for(;;) {
186 getc1();
187 }
188
189 /* [ \t]+ eat first space */ 230 /* [ \t]+ eat first space */
190 while(c == ' ' || c == '\t') 231 while(c == ' ' || c == '\t')
191 getc1(); 232 getc1();
192 233
193 if(c == BS) {
194 getc1();
195 if(c == '\n') {
196 /* \\\n eat continued */
197 line++;
198 prev_state = NLC;
199 continue;
200 }
201 ungetc1();
202 c = BS;
203 }
204
205 if(state == S) { 234 if(state == S) {
206 while(first_chars[c] == ANY) { 235 while(first_chars[c] == ANY) {
207 /* <S>unparsed */ 236 /* <S>unparsed */
@@ -211,33 +240,44 @@ static void c_lex(const char *fname, long fsize)
211 } 240 }
212 if(c == L_EOF) { 241 if(c == L_EOF) {
213 /* <S><<EOF>> */ 242 /* <S><<EOF>> */
214 id_s = id;
215 mema_id = local_mema_id;
216 munmap(map, mapsize); 243 munmap(map, mapsize);
217 close(fd); 244 close(fd);
218 return; 245 return;
219 } 246 }
220 if(c == REM) { 247 if(c == REM) {
221 /* <S>/ */ 248 /* <S>/ */
222 getc1(); /* eat <S>/ */ 249 getc0();
223 if(c == REM) { 250 if(c == REM) {
224 /* <S>"//"[^\n]* */ 251 /* <S>"//"[^\n]* */
225 do getc1(); while(c != '\n' && c != L_EOF); 252 do getc0(); while(c != '\n' && c != L_EOF);
226 } else if(c == '*') { 253 } else if(c == '*') {
227 /* <S>[/][*] */ 254 /* <S>[/][*] goto parse block comments */
228 called = S; 255 break;
229 state = REM;
230 } 256 }
231 } else if(c == POUND) { 257 } else if(c == POUND) {
232 /* <S># */ 258 /* <S># */
233 start = optr - 1;
234 state = c; 259 state = c;
260 getc1();
235 } else if(c == STR || c == CHR) { 261 } else if(c == STR || c == CHR) {
236 /* <S>\"|\' */ 262 /* <S>\"|\' */
237 val = NULL; 263 int qc = c;
238 called = S; 264
239 state = c; 265 for(;;) {
240 } else if(c != BS) { 266 /* <STR,CHR>. */
267 getc1();
268 if(c == qc) {
269 /* <STR>\" or <CHR>\' */
270 break;
271 }
272 if(c == BS) {
273 /* <STR,CHR>\\ but is not <STR,CHR>\\\n */
274 getc0();
275 }
276 if(c == '\n' || c == L_EOF)
277 yy_error_d("unterminated");
278 }
279 getc1();
280 } else {
241 /* <S>[A-Z_a-z0-9] */ 281 /* <S>[A-Z_a-z0-9] */
242 282
243 /* trick for fast drop id 283 /* trick for fast drop id
@@ -254,90 +294,20 @@ static void c_lex(const char *fname, long fsize)
254 } while(isalnums[c]); 294 } while(isalnums[c]);
255 check_key(key_top, id, id_len); 295 check_key(key_top, id, id_len);
256 } 296 }
257 } else {
258 /* <S>\\ */
259 prev_state = c;
260 } 297 }
261 continue; 298 continue;
262 } 299 }
263 if(state == REM) {
264 for(;;) {
265 /* <REM>[^*]+ */
266 while(c != '*') {
267 if(c == '\n') {
268 /* <REM>\n */
269 if(called != S)
270 yy_error_d("unexpected newline");
271 line++;
272 } else if(c == L_EOF)
273 yy_error_d("unexpected EOF");
274 getc1();
275 }
276 /* <REM>[*] */
277 getc1();
278 if(c == REM) {
279 /* <REM>[*][/] */
280 state = called;
281 break;
282 }
283 }
284 continue;
285 }
286 if(state == STR || state == CHR) {
287 for(;;) {
288 /* <STR,CHR>\n|<<EOF>> */
289 if(c == '\n' || c == L_EOF)
290 yy_error_d("unterminated");
291 if(c == BS) {
292 /* <STR,CHR>\\ */
293 getc1();
294 if(c != BS && c != '\n' && c != state) {
295 /* another usage \ in str or char */
296 if(c == L_EOF)
297 yy_error_d("unexpected EOF");
298 if(val)
299 put_id(c);
300 continue;
301 }
302 /* <STR,CHR>\\[\\\n] or <STR>\\\" or <CHR>\\\' */
303 /* eat 2 char */
304 if(c == '\n')
305 line++;
306 else if(val)
307 put_id(c);
308 } else if(c == state) {
309 /* <STR>\" or <CHR>\' */
310 if(called == LI) {
311 /* store "include.h" */
312 parse_inc(id, fname, id_len);
313 } else if(called == DV) {
314 put_id(c); /* config mode #define KEY "VAL"<- */
315 put_id(0);
316 parse_conf_opt(id, val, (optr - start), opt_len);
317 }
318 state = S;
319 break;
320 } else if(val)
321 put_id(c);
322 /* <STR,CHR>. */
323 getc1();
324 }
325 continue;
326 }
327
328 /* begin preprocessor states */ 300 /* begin preprocessor states */
329 if(c == L_EOF) 301 if(c == L_EOF)
330 yy_error_d("unexpected EOF"); 302 yy_error_d("unexpected EOF");
331 if(c == REM) { 303 if(c == REM) {
332 /* <#.*>/ */ 304 /* <#.*>/ */
333 getc1(); 305 getc0();
334 if(c == REM) 306 if(c == REM)
335 yy_error_d("detected // in preprocessor line"); 307 yy_error_d("detected // in preprocessor line");
336 if(c == '*') { 308 if(c == '*') {
337 /* <#.*>[/][*] */ 309 /* <#.*>[/][*] goto parse block comments */
338 called = state; 310 break;
339 state = REM;
340 continue;
341 } 311 }
342 /* hmm, #.*[/] */ 312 /* hmm, #.*[/] */
343 yy_error_d("strange preprocessor line"); 313 yy_error_d("strange preprocessor line");
@@ -345,43 +315,49 @@ static void c_lex(const char *fname, long fsize)
345 if(state == POUND) { 315 if(state == POUND) {
346 /* tricks */ 316 /* tricks */
347 static const char * const preproc[] = { 317 static const char * const preproc[] = {
348 /* 0-3 */ 318 /* 0 1 2 3 4 5 6 */
349 "", "", "", "", 319 "", "", "", "", "ndef", "efine", "nclude"
350 /* 4 */ /* 5 */ /* 6 */
351 "ndef", "efine", "nclude",
352 }; 320 };
353 size_t diu = first_chars_diu[c]; /* strlen and preproc ptr */ 321 size_t diu = first_chars_diu[c]; /* strlen and preproc ptr */
354 const unsigned char *p = optr;
355 322
356 while(isalnums[c]) getc1(); 323 state = S;
357 /* have str begined with c, readed == strlen key and compared */ 324 if(diu != S) {
358 if(diu != S && diu == (optr-p-1) && !memcmp(p, preproc[diu], diu)) { 325 getc1();
359 state = p[-1]; 326 id_len = 0;
360 id_len = 0; /* common for save */ 327 while(isalnums[c]) {
328 put_id(c);
329 getc1();
330 }
331 /* have str begined with c, readed == strlen key and compared */
332 if(diu == id_len && !memcmp(id, preproc[diu], diu)) {
333 state = diu + '0';
334 id_len = 0; /* common for save */
335 }
361 } else { 336 } else {
362 state = S; 337 while(isalnums[c]) getc1();
363 } 338 }
364 ungetc1(); 339 } else if(state == I) {
365 continue;
366 }
367 if(state == I) {
368 if(c == STR) { 340 if(c == STR) {
369 /* <I>\" */ 341 /* <I>\" */
370 val = id; 342 for(;;) {
371 called = LI; 343 getc1();
372 state = STR; 344 if(c == STR)
373 } else { 345 break;
374 /* another (may be wrong) #include ... */ 346 if(c == L_EOF)
375 ungetc1(); 347 yy_error_d("unexpected EOF");
376 state = S; 348 put_id(c);
349 }
350 put_id(0);
351 /* store "include.h" */
352 parse_inc(id, fname);
353 getc1();
377 } 354 }
378 continue; 355 /* else another (may be wrong) #include ... */
379 } 356 state = S;
380 if(state == D || state == U) { 357 } else if(state == D || state == U) {
381 if(mode == SOURCES_MODE) { 358 if(mode == SOURCES_MODE) {
382 /* ignore depend with #define or #undef KEY */ 359 /* ignore depend with #define or #undef KEY */
383 while(isalnums[c]) 360 while(isalnums[c]) getc1();
384 getc1();
385 state = S; 361 state = S;
386 } else { 362 } else {
387 /* save KEY from #"define"|"undef" ... */ 363 /* save KEY from #"define"|"undef" ... */
@@ -392,145 +368,164 @@ static void c_lex(const char *fname, long fsize)
392 if(!id_len) 368 if(!id_len)
393 yy_error_d("expected identifier"); 369 yy_error_d("expected identifier");
394 if(state == U) { 370 if(state == U) {
395 parse_conf_opt(id, NULL, (optr - start), id_len); 371 parse_conf_opt(id, NULL, id_len);
396 state = S; 372 state = S;
397 } else { 373 } else {
398 /* D -> DK */ 374 /* D -> DK */
399 opt_len = id_len; 375 if(c == '(')
376 yy_error_d("unexpected function macro");
400 state = DK; 377 state = DK;
401 } 378 }
402 } 379 }
403 ungetc1(); 380 } else {
404 continue; 381 /* state==<DK> #define KEY[ ] (config mode) */
405 } 382 size_t opt_len = id_len;
406 if(state == DK) { 383 char *val = id + opt_len;
407 /* #define KEY[ ] (config mode) */ 384 char *sp;
408 val = id + id_len; 385
409 if(c == STR || c == CHR) { 386 for(;;) {
410 /* define KEY "... or define KEY '... */ 387 if(c == L_EOF || c == '\n')
411 put_id(c); 388 break;
412 called = DV;
413 state = c;
414 continue;
415 }
416 while(isalnums[c]) {
417 /* VALUE */
418 put_id(c); 389 put_id(c);
419 getc1(); 390 getc1();
420 } 391 }
392 sp = id + id_len;
421 put_id(0); 393 put_id(0);
422 parse_conf_opt(id, val, (optr - start), opt_len); 394 /* trim tail spaces */
395 while(--sp >= val && (*sp == ' ' || *sp == '\t'
396 || *sp == '\f' || *sp == '\v'))
397 *sp = '\0';
398 parse_conf_opt(id, val, opt_len);
423 state = S; 399 state = S;
424 ungetc1();
425 continue;
426 } 400 }
427 } 401 }
402
403 /* <REM> */
404 getc0();
405 for(;;) {
406 /* <REM>[^*]+ */
407 while(c != '*') {
408 if(c == '\n') {
409 /* <REM>\n */
410 if(state != S)
411 yy_error_d("unexpected newline");
412 line++;
413 } else if(c == L_EOF)
414 yy_error_d("unexpected EOF");
415 getc0();
416 }
417 /* <REM>[*] */
418 getc0();
419 if(c == REM) {
420 /* <REM>[*][/] */
421 break;
422 }
423 }
424 }
425too_long:
426 yy_error_d("phrase too long");
428} 427}
429 428
430 429
431static void show_usage(void) __attribute__ ((noreturn)); 430/* bb_simplify_path special variant for apsolute pathname */
432static void show_usage(void) 431static size_t bb_qa_simplify_path(char *path)
433{ 432{
434 bb_error_d("%s\n%s\n", bb_mkdep_terse_options, bb_mkdep_full_options); 433 char *s, *p;
435}
436 434
437static const char *kp; 435 p = s = path;
438static size_t kp_len;
439static llist_t *Iop;
440static bb_key_t *Ifound;
441static int noiwarning;
442 436
443static bb_key_t *check_key(bb_key_t *k, const char *nk, size_t key_sz) 437 do {
444{ 438 if (*p == '/') {
445 bb_key_t *cur; 439 if (*s == '/') { /* skip duplicate (or initial) slash */
440 continue;
441 } else if (*s == '.') {
442 if (s[1] == '/' || s[1] == 0) { /* remove extra '.' */
443 continue;
444 } else if ((s[1] == '.') && (s[2] == '/' || s[2] == 0)) {
445 ++s;
446 if (p > path) {
447 while (*--p != '/'); /* omit previous dir */
448 }
449 continue;
450 }
451 }
452 }
453 *++p = *s;
454 } while (*++s);
446 455
447 for(cur = k; cur; cur = cur->next) { 456 if ((p == path) || (*p != '/')) { /* not a trailing slash */
448 if(key_sz == cur->key_sz && memcmp(cur->keyname, nk, key_sz) == 0) { 457 ++p; /* so keep last character */
449 cur->checked = cur->stored_path;
450 return cur;
451 } 458 }
452 } 459 *p = 0;
453 return NULL;
454}
455
456static bb_key_t *make_new_key(bb_key_t *k, const char *nk, size_t key_sz)
457{
458 bb_key_t *cur;
459 460
460 cur = xmalloc(sizeof(bb_key_t) + key_sz + 1); 461 return (p - path);
461 cur->keyname = memcpy(cur + 1, nk, key_sz);
462 cur->keyname[key_sz] = '\0';
463 cur->key_sz = key_sz;
464 cur->checked = NULL;
465 cur->next = k;
466 return cur;
467} 462}
468 463
469static inline char *store_include_fullpath(char *p_i, bb_key_t *li) 464static void parse_inc(const char *include, const char *fname)
470{ 465{
471 char *ok; 466 bb_key_t *cur;
472 467 const char *p_i;
473 if(access(p_i, F_OK) == 0) { 468 llist_t *lo;
474 ok = li->stored_path = bb_simplify_path(p_i); 469 char *ap;
475 li->checked = ok; 470 size_t key_sz;
471
472 if(*include == '/') {
473 lo = NULL;
474 ap = bb_xstrdup(include);
476 } else { 475 } else {
477 ok = NULL; 476 int w;
477 const char *p;
478
479 lo = Iop;
480 p = strrchr(fname, '/'); /* fname have absolute pathname */
481 w = (p-fname);
482 /* find from current directory of source file */
483 ap = bb_asprint("%.*s/%s", w, fname, include);
478 } 484 }
479 free(p_i);
480 return ok;
481}
482
483static void parse_inc(const char *include, const char *fname, size_t key_sz)
484{
485 bb_key_t *li;
486 char *p_i;
487 llist_t *lo;
488 485
489 li = check_key(Ifound, include, key_sz); 486 for(;;) {
490 if(li) 487 key_sz = bb_qa_simplify_path(ap);
488 cur = check_key(Ifound, ap, key_sz);
489 if(cur) {
490 cur->checked = cur->value;
491 free(ap);
491 return; 492 return;
492 Ifound = li = make_new_key(Ifound, include, key_sz);
493 include = li->keyname;
494 if(include[0] != '/') {
495 /* relative */
496 int w;
497
498 p_i = strrchr(fname, '/'); /* fname have absolute pathname */
499 w = (p_i-fname);
500 /* find from current directory of source file */
501 p_i = bb_asprint("%.*s/%s", w, fname, include);
502 if(store_include_fullpath(p_i, li))
503 return;
504 /* find from "-I include" specified directories */
505 for(lo = Iop; lo; lo = lo->link) {
506 p_i = bb_asprint("%s/%s", lo->data, include);
507 if(store_include_fullpath(p_i, li))
508 return;
509 }
510 } else {
511 /* absolute include pathname */
512 if(access(include, F_OK) == 0) {
513 li->checked = li->stored_path = bb_xstrdup(include);
514 return;
515 }
516 } 493 }
517 li->stored_path = NULL; 494 if(access(ap, F_OK) == 0) {
518 if(noiwarning) 495 /* found */
519 fprintf(stderr, "%s: Warning: #include \"%s\" not found in specified paths\n", fname, include); 496 p_i = ap;
497 break;
498 } else if(lo == NULL) {
499 p_i = NULL;
500 break;
501 }
502
503 /* find from "-I include" specified directories */
504 free(ap);
505 /* lo->data have absolute pathname */
506 ap = bb_asprint("%s/%s", lo->data, include);
507 lo = lo->link;
508 }
509
510 cur = xmalloc(sizeof(bb_key_t));
511 cur->keyname = ap;
512 cur->key_sz = key_sz;
513 cur->stored_path = ap;
514 cur->value = cur->checked = p_i;
515 if(p_i == NULL && noiwarning)
516 fprintf(stderr, "%s: Warning: #include \"%s\" not found\n", fname, include);
517 cur->next = Ifound;
518 Ifound = cur;
520} 519}
521 520
522static void parse_conf_opt(const char *opt, const char *val, 521static size_t max_rec_sz;
523 size_t recordsz, size_t key_sz) 522
523static void parse_conf_opt(const char *opt, const char *val, size_t key_sz)
524{ 524{
525 bb_key_t *cur; 525 bb_key_t *cur;
526 char *k; 526 char *k;
527 char *s, *p; 527 char *p;
528 struct stat st; 528 size_t val_sz = 0;
529 int fd;
530 int cmp_ok = 0;
531 static char *record_buf;
532 static size_t r_sz;
533 ssize_t rw_ret;
534 529
535 cur = check_key(key_top, opt, key_sz); 530 cur = check_key(key_top, opt, key_sz);
536 if(cur != NULL) { 531 if(cur != NULL) {
@@ -543,29 +538,33 @@ static void parse_conf_opt(const char *opt, const char *val,
543 k = cur->keyname; 538 k = cur->keyname;
544 fprintf(stderr, "Warning: redefined %s\n", k); 539 fprintf(stderr, "Warning: redefined %s\n", k);
545 } else { 540 } else {
546 key_top = cur = make_new_key(key_top, opt, key_sz); 541 size_t recordsz;
547 k = cur->keyname; 542
543 if(val && *val)
544 val_sz = strlen(val) + 1;
545 recordsz = key_sz + val_sz + 1;
546 if(max_rec_sz < recordsz)
547 max_rec_sz = recordsz;
548 cur = xmalloc(sizeof(bb_key_t) + recordsz);
549 k = cur->keyname = memcpy(cur + 1, opt, key_sz);
550 cur->keyname[key_sz] = '\0';
551 cur->key_sz = key_sz;
552 cur->checked = NULL;
553 cur->src_have_this_key = NULL;
554 cur->next = key_top;
555 key_top = cur;
548 } 556 }
549 /* do generate record */ 557 /* save VAL */
550 recordsz += 2; /* \n\0 */
551 if(recordsz > r_sz)
552 record_buf = xrealloc(record_buf, (r_sz = recordsz) * 2);
553 s = record_buf;
554 /* may be short count " " */
555 if(val) { 558 if(val) {
556 if(*val == '\0') { 559 if(*val == '\0') {
557 cur->value = ""; 560 cur->value = "";
558 recordsz = sprintf(s, "#define %s\n", k);
559 } else { 561 } else {
560 cur->value = bb_xstrdup(val); 562 cur->value = p = cur->keyname + key_sz + 1;
561 recordsz = sprintf(s, "#define %s %s\n", k, val); 563 memcpy(p, val, val_sz);
562 } 564 }
563 } else { 565 } else {
564 cur->value = NULL; 566 cur->value = NULL;
565 recordsz = sprintf(s, "#undef %s\n", k);
566 } 567 }
567 /* size_t -> ssize_t :( */
568 rw_ret = (ssize_t)recordsz;
569 /* trick, save first char KEY for do fast identify id */ 568 /* trick, save first char KEY for do fast identify id */
570 first_chars[(int)*k] = *k; 569 first_chars[(int)*k] = *k;
571 570
@@ -577,80 +576,118 @@ static void parse_conf_opt(const char *opt, const char *val,
577 else if(*p == '_' && p[1] > '9') /* do not change A_1 to A/1 */ 576 else if(*p == '_' && p[1] > '9') /* do not change A_1 to A/1 */
578 *p = '/'; 577 *p = '/';
579 } 578 }
580 /* check kp/key.h if present after previous usage */ 579}
581 if(stat(k, &st)) { 580
582 for(p = k + kp_len + 1; *p; p++) { 581static void store_keys(void)
583 /* Auto-create directories. */ 582{
584 if (*p == '/') { 583 bb_key_t *cur;
585 *p = '\0'; 584 char *k;
586 if (access(k, F_OK) != 0 && mkdir(k, 0755) != 0) 585 struct stat st;
587 bb_error_d("mkdir(%s): %m", k); 586 int cmp_ok;
588 *p = '/'; 587 ssize_t rw_ret;
588 size_t recordsz = max_rec_sz * 2 + 10 * 2 + 16;
589 /* buffer for double "#define KEY VAL\n" */
590 char *record_buf = xmalloc(recordsz);
591
592 for(cur = key_top; cur; cur = cur->next) {
593 if(cur->src_have_this_key) {
594 /* do generate record */
595 k = cur->keyname;
596 if(cur->value == NULL) {
597 recordsz = sprintf(record_buf, "#undef %s\n", k);
598 } else {
599 const char *val = cur->value;
600 if(*val == '\0') {
601 recordsz = sprintf(record_buf, "#define %s\n", k);
602 } else {
603 recordsz = sprintf(record_buf, "#define %s %s\n", k, val);
589 } 604 }
590 } 605 }
591 } else { 606 /* size_t -> ssize_t :( */
592 /* found */ 607 rw_ret = (ssize_t)recordsz;
593 if(st.st_size == (off_t)recordsz) { 608 /* check kp/key.h, compare after previous usage */
594 char *r_cmp = s + recordsz; 609 cmp_ok = 0;
595 610 k = cur->stored_path;
596 fd = open(k, O_RDONLY); 611 if(stat(k, &st)) {
597 if(fd < 0 || read(fd, r_cmp, recordsz) < rw_ret) 612 char *p;
598 bb_error_d("%s: %m", k); 613 for(p = k + kp_len + 1; *p; p++) {
599 close(fd); 614 /* Auto-create directories. */
600 cmp_ok = memcmp(s, r_cmp, recordsz) == 0; 615 if (*p == '/') {
616 *p = '\0';
617 if (access(k, F_OK) != 0 && mkdir(k, 0755) != 0)
618 bb_error_d("mkdir(%s): %m", k);
619 *p = '/';
620 }
601 } 621 }
622 } else {
623 /* found */
624 if(st.st_size == (off_t)recordsz) {
625 char *r_cmp;
626 int fd;
627 size_t padded = recordsz;
628
629 /* 16-byte padding for read(2) and memcmp(3) */
630 padded = (padded+15) & ~15;
631 r_cmp = record_buf + padded;
632 fd = open(k, O_RDONLY);
633 if(fd < 0 || read(fd, r_cmp, recordsz) < rw_ret)
634 bb_error_d("%s: %m", k);
635 close(fd);
636 cmp_ok = memcmp(record_buf, r_cmp, recordsz) == 0;
637 }
638 }
639 if(!cmp_ok) {
640 int fd = open(k, O_WRONLY|O_CREAT|O_TRUNC, 0644);
641 if(fd < 0 || write(fd, record_buf, recordsz) < rw_ret)
642 bb_error_d("%s: %m", k);
643 close(fd);
644 }
602 } 645 }
603 if(!cmp_ok) { 646 }
604 fd = open(k, O_WRONLY|O_CREAT|O_TRUNC, 0644);
605 if(fd < 0 || write(fd, s, recordsz) < rw_ret)
606 bb_error_d("%s: %m", k);
607 close(fd);
608 }
609} 647}
610 648
611static char *pwd;
612
613static int show_dep(int first, bb_key_t *k, const char *name, const char *f) 649static int show_dep(int first, bb_key_t *k, const char *name, const char *f)
614{ 650{
615 bb_key_t *cur; 651 bb_key_t *cur;
616 652
617 for(cur = k; cur; cur = cur->next) { 653 for(cur = k; cur; cur = cur->next) {
618 if(cur->checked) { 654 if(cur->checked) {
619 if(first) { 655 if(first >= 0) {
620 if(f == NULL) 656 if(first) {
657 if(f == NULL)
621 printf("\n%s:", name); 658 printf("\n%s:", name);
622 else 659 else
623 printf("\n%s/%s:", pwd, name); 660 printf("\n%s/%s:", pwd, name);
624 first = 0; 661 first = 0;
625 } else { 662 } else {
626 printf(" \\\n "); 663 printf(" \\\n ");
664 }
665 printf(" %s", cur->checked);
627 } 666 }
628 printf(" %s", cur->checked); 667 cur->src_have_this_key = cur->checked;
668 cur->checked = NULL;
629 } 669 }
630 cur->checked = NULL;
631 } 670 }
632 return first; 671 return first;
633} 672}
634 673
635static size_t replace;
636
637static struct stat st_kp;
638static int dontgenerate_dep;
639
640static char * 674static char *
641parse_chd(const char *fe, const char *p, size_t dirlen) 675parse_chd(const char *fe, const char *p, size_t dirlen)
642{ 676{
643 struct stat st; 677 struct stat st;
644 char *fp; 678 char *fp;
645 size_t df_sz; 679 size_t df_sz;
646 static char *dir_and_entry; 680 static char dir_and_entry[4096];
647 static size_t dir_and_entry_sz; 681 size_t fe_sz = strlen(fe) + 1;
648 682
649 df_sz = dirlen + strlen(fe) + 2; /* dir/file\0 */ 683 df_sz = dirlen + fe_sz + 1; /* dir/file\0 */
650 if(df_sz > dir_and_entry_sz) 684 if(df_sz > sizeof(dir_and_entry))
651 dir_and_entry = xrealloc(dir_and_entry, dir_and_entry_sz = df_sz); 685 bb_error_d("%s: file name too long", fe);
652 fp = dir_and_entry; 686 fp = dir_and_entry;
653 sprintf(fp, "%s/%s", p, fe); 687 /* sprintf(fp, "%s/%s", p, fe); */
688 memcpy(fp, p, dirlen);
689 fp[dirlen] = '/';
690 memcpy(fp + dirlen + 1, fe, fe_sz);
654 691
655 if(stat(fp, &st)) { 692 if(stat(fp, &st)) {
656 fprintf(stderr, "Warning: stat(%s): %m\n", fp); 693 fprintf(stderr, "Warning: stat(%s): %m\n", fp);
@@ -673,17 +710,16 @@ parse_chd(const char *fe, const char *p, size_t dirlen)
673 } 710 }
674 } 711 }
675 /* direntry is *.[ch] regular file and is not configs */ 712 /* direntry is *.[ch] regular file and is not configs */
713 c_lex(fp, st.st_size);
676 if(!dontgenerate_dep) { 714 if(!dontgenerate_dep) {
677 int first; 715 int first;
678
679 c_lex(fp, st.st_size);
680 if(*e == 'c') { 716 if(*e == 'c') {
681 /* *.c -> *.o */ 717 /* *.c -> *.o */
682 *e = 'o'; 718 *e = 'o';
683 /* /src_dir/path/file.o to path/file.o */ 719 /* /src_dir/path/file.o to path/file.o */
684 fp += replace; 720 fp += replace;
685 if(*fp == '/') 721 if(*fp == '/')
686 fp++; 722 fp++;
687 } else { 723 } else {
688 e = NULL; 724 e = NULL;
689 } 725 }
@@ -691,15 +727,15 @@ parse_chd(const char *fe, const char *p, size_t dirlen)
691 first = show_dep(first, key_top, fp, e); 727 first = show_dep(first, key_top, fp, e);
692 if(first == 0) 728 if(first == 0)
693 putchar('\n'); 729 putchar('\n');
730 } else {
731 show_dep(-1, key_top, NULL, NULL);
694 } 732 }
695 return NULL; 733 return NULL;
696 } else if(S_ISDIR(st.st_mode)) { 734 } else if(S_ISDIR(st.st_mode)) {
697 if (st.st_dev == st_kp.st_dev && st.st_ino == st_kp.st_ino) 735 if (st.st_dev == st_kp.st_dev && st.st_ino == st_kp.st_ino)
698 return NULL; /* drop scan kp/ directory */ 736 return NULL; /* drop scan kp/ directory */
699 /* direntry is directory. buff is returned, begin of zero allocate */ 737 /* direntry is directory. buff is returned */
700 dir_and_entry = NULL; 738 return bb_xstrdup(fp);
701 dir_and_entry_sz = 0;
702 return fp;
703 } 739 }
704 /* hmm, direntry is device! */ 740 /* hmm, direntry is device! */
705 return NULL; 741 return NULL;
@@ -755,6 +791,11 @@ static void scan_dir_find_ch_files(const char *p)
755 } 791 }
756} 792}
757 793
794static void show_usage(void) __attribute__ ((noreturn));
795static void show_usage(void)
796{
797 bb_error_d("%s\n%s\n", bb_mkdep_terse_options, bb_mkdep_full_options);
798}
758 799
759int main(int argc, char **argv) 800int main(int argc, char **argv)
760{ 801{
@@ -763,24 +804,25 @@ int main(int argc, char **argv)
763 llist_t *fl; 804 llist_t *fl;
764 805
765 { 806 {
766 /* for bb_simplify_path */ 807 /* for bb_simplify_path, this program have not chdir() */
767 /* libbb xgetcwd(), this program have not chdir() */ 808 /* libbb-like my xgetcwd() */
768 unsigned path_max = 512; 809 unsigned path_max = 512;
769 810
770 s = xmalloc (path_max); 811 s = xmalloc (path_max);
771#define PATH_INCR 32
772 while (getcwd (s, path_max) == NULL) { 812 while (getcwd (s, path_max) == NULL) {
773 if(errno != ERANGE) 813 if(errno != ERANGE)
774 bb_error_d("getcwd: %m"); 814 bb_error_d("getcwd: %m");
775 s = xrealloc (s, path_max += PATH_INCR); 815 free(s);
776 } 816 s = xmalloc(path_max *= 2);
817 }
777 pwd = s; 818 pwd = s;
778 } 819 }
779 820
780 while ((i = getopt(argc, argv, "I:c:dk:w")) > 0) { 821 while ((i = getopt(argc, argv, "I:c:dk:w")) > 0) {
781 switch(i) { 822 switch(i) {
782 case 'I': 823 case 'I':
783 Iop = llist_add_to(Iop, optarg); 824 s = bb_simplify_path(optarg);
825 Iop = llist_add_to(Iop, s);
784 break; 826 break;
785 case 'c': 827 case 'c':
786 s = bb_simplify_path(optarg); 828 s = bb_simplify_path(optarg);
@@ -812,19 +854,18 @@ int main(int argc, char **argv)
812 bb_error_d("%s is not directory", kp); 854 bb_error_d("%s is not directory", kp);
813 /* defaults */ 855 /* defaults */
814 if(Iop == NULL) 856 if(Iop == NULL)
815 Iop = llist_add_to(Iop, LOCAL_INCLUDE_PATH); 857 Iop = llist_add_to(Iop, bb_simplify_path(LOCAL_INCLUDE_PATH));
816 if(configs == NULL) { 858 if(configs == NULL) {
817 s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH); 859 s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH);
818 configs = llist_add_to(configs, s); 860 configs = llist_add_to(configs, s);
819 } 861 }
820 /* for c_lex */ 862 /* for c_lex */
821 pagesizem1 = getpagesize() - 1; 863 pagesizem1 = getpagesize() - 1;
822 id_s = xmalloc(mema_id); 864 for(i = 0; i < UCHAR_MAX; i++) {
823 for(i = 0; i < 256; i++) {
824 if(ISALNUM(i)) 865 if(ISALNUM(i))
825 isalnums[i] = i; 866 isalnums[i] = i;
826 /* set unparsed chars for speed up of parser */ 867 /* set unparsed chars for speed up of parser */
827 else if(i != CHR && i != STR && i != POUND && i != REM && i != BS) 868 else if(i != CHR && i != STR && i != POUND && i != REM)
828 first_chars[i] = ANY; 869 first_chars[i] = ANY;
829 } 870 }
830 first_chars[i] = '-'; /* L_EOF */ 871 first_chars[i] = '-'; /* L_EOF */
@@ -836,8 +877,9 @@ int main(int argc, char **argv)
836 if(stat(fl->data, &st)) 877 if(stat(fl->data, &st))
837 bb_error_d("stat(%s): %m", fl->data); 878 bb_error_d("stat(%s): %m", fl->data);
838 c_lex(fl->data, st.st_size); 879 c_lex(fl->data, st.st_size);
880 free(fl->data);
839 /* trick for fast comparing found files with configs */ 881 /* trick for fast comparing found files with configs */
840 fl->data = xrealloc(fl->data, sizeof(struct stat)); 882 fl->data = xmalloc(sizeof(struct stat));
841 memcpy(fl->data, &st, sizeof(struct stat)); 883 memcpy(fl->data, &st, sizeof(struct stat));
842 } 884 }
843 885
@@ -850,6 +892,7 @@ int main(int argc, char **argv)
850 } else { 892 } else {
851 scan_dir_find_ch_files("."); 893 scan_dir_find_ch_files(".");
852 } 894 }
895 store_keys();
853 return 0; 896 return 0;
854} 897}
855 898
@@ -881,30 +924,6 @@ static char *bb_asprint(const char *format, ...)
881} 924}
882 925
883/* partial libbb routine as is */ 926/* partial libbb routine as is */
884static void *xmalloc(size_t size)
885{
886 void *p = malloc(size);
887
888 if(p == NULL)
889 bb_error_d(msg_enomem);
890 return p;
891}
892
893static void *xrealloc(void *p, size_t size) {
894 p = realloc(p, size);
895 if(p == NULL)
896 bb_error_d(msg_enomem);
897 return p;
898}
899
900static char *bb_xstrdup(const char *s)
901{
902 char *r = strdup(s);
903
904 if(r == NULL)
905 bb_error_d(msg_enomem);
906 return r;
907}
908 927
909static char *bb_simplify_path(const char *path) 928static char *bb_simplify_path(const char *path)
910{ 929{