blob: 76db960fdd42f4ee6c83b0efea65a96e31782c7c [file] [log] [blame]
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +00001/*
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +00002 * Another fast dependencies generator for Makefiles, Version 2.5
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +00003 *
4 * Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru>
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +00005 * mmaping file may be originally by Linus Torvalds.
6 *
7 * (c) 2005 Bernhard Fischer:
8 * - commentary typos,
9 * - move "memory exhausted" into msg_enomem,
10 * - more verbose --help output.
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000011 *
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000012 * This program does:
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000013 * 1) find #define KEY VALUE or #undef KEY from include/config.h
14 * 2) save include/config/key*.h if changed after previous usage
"Vladimir N. Oleynik"664c6e72005-10-06 14:53:43 +000015 * 3) recursive find and scan *.[ch] files, but skips scan of include/config/
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000016 * 4) find #include "*.h" and KEYs using, if not as #define and #undef
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000017 * 5) generate dependencies to stdout
"Vladimir N. Oleynik"664c6e72005-10-06 14:53:43 +000018 * pwd/file.o: include/config/key*.h found_include_*.h
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000019 * path/inc.h: include/config/key*.h found_included_include_*.h
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +000020 * This program does not generate dependencies for #include <...>
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +000021 * BUG: all includes name must unique
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000022 */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000023
24#define LOCAL_INCLUDE_PATH "include"
25#define INCLUDE_CONFIG_PATH LOCAL_INCLUDE_PATH"/config"
26#define INCLUDE_CONFIG_KEYS_PATH LOCAL_INCLUDE_PATH"/config.h"
27
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000028#define bb_mkdep_full_options \
29"\nOptions:" \
30"\n\t-I local_include_path include paths, default: \"" LOCAL_INCLUDE_PATH "\"" \
31"\n\t-d don't generate depend" \
32"\n\t-w show warning if include files not found" \
33"\n\t-k include/config default: \"" INCLUDE_CONFIG_PATH "\"" \
34"\n\t-c include/config.h configs, default: \"" INCLUDE_CONFIG_KEYS_PATH "\"" \
35"\n\tdirs_to_scan default \".\""
36
37#define bb_mkdep_terse_options "Usage: [-I local_include_paths] [-dw] " \
38 "[-k path_for_stored_keys] [dirs]"
39
40
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000041#define _GNU_SOURCE
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <sys/mman.h>
45#include <getopt.h>
46#include <dirent.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <stdarg.h>
51#include <unistd.h>
52#include <errno.h>
53#include <fcntl.h>
54
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000055
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000056typedef struct BB_KEYS {
57 char *keyname;
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +000058 size_t key_sz;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000059 const char *value;
60 char *stored_path;
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +000061 char *checked;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000062 struct BB_KEYS *next;
63} bb_key_t;
64
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +000065static 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);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000067
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000068/* partial and simplified libbb routine */
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +000069static 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)));
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000071
72/* stolen from libbb as is */
73typedef struct llist_s {
74 char *data;
75 struct llist_s *link;
76} llist_t;
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +000077static void *xrealloc(void *p, size_t size);
78static void *xmalloc(size_t size);
79static char *bb_xstrdup(const char *s);
80static char *bb_simplify_path(const char *path);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000081/* error messages */
82static const char msg_enomem[] = "memory exhausted";
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000083
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000084/* for lexical analyser */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000085static bb_key_t *key_top;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +000086static llist_t *configs;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000087
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000088static int mode;
89#define CONFIG_MODE 0
90#define SOURCES_MODE 1
91
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +000092static void parse_inc(const char *include, const char *fname, size_t key_sz);
93static void parse_conf_opt(const char *opt, const char *val,
94 size_t rsz, size_t key_sz);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000095
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000096/* for speed tricks */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +000097static char first_chars[257]; /* + L_EOF */
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +000098static char isalnums[257]; /* + L_EOF */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000099/* trick for fast find "define", "include", "undef" */
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000100static char first_chars_diu[256] = {
101 [(int)'d'] = (char)5, /* strlen("define") - 1; */
102 [(int)'i'] = (char)6, /* strlen("include") - 1; */
103 [(int)'u'] = (char)4, /* strlen("undef") - 1; */
104};
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000105
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000106static int pagesizem1;
107static size_t mema_id = 128; /* first allocated for id */
108static char *id_s;
109
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000110
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000111#define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s)
112
113/* state */
114#define S 0 /* start state */
115#define STR '"' /* string */
116#define CHR '\'' /* char */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000117#define REM '/' /* block comment */
118#define BS '\\' /* back slash */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000119#define POUND '#' /* # */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000120#define I 'i' /* #include preprocessor's directive */
121#define D 'd' /* #define preprocessor's directive */
122#define U 'u' /* #undef preprocessor's directive */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000123#define LI 'I' /* #include "... */
124#define DK 'K' /* #define KEY... (config mode) */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000125#define DV 'V' /* #define KEY "VALUE or #define KEY 'VALUE */
126#define NLC 'n' /* \ and \n */
127#define ANY '*' /* any unparsed chars */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000128
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000129#define L_EOF 256
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000130/* [A-Z_a-z] */
131#define ID(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_')
132/* [A-Z_a-z0-9] */
133#define ISALNUM(c) (ID(c) || (c >= '0' && c <= '9'))
134
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000135#define getc1() do { c = (optr >= oend) ? L_EOF : *optr++; } while(0)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000136#define ungetc1() optr--
137
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000138#define put_id(c) do { if(id_len == local_mema_id) \
139 id = xrealloc(id, local_mema_id += 16); \
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000140 id[id_len++] = c; } while(0)
141
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000142
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000143/* stupid C lexical analyser */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000144static void c_lex(const char *fname, long fsize)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000145{
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000146 int c = L_EOF; /* stupid initialize */
147 int prev_state = L_EOF;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000148 int called;
149 int state;
150 int line;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000151 char *id = id_s;
152 size_t local_mema_id = mema_id;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000153 size_t id_len = 0; /* stupid initialize */
154 char *val = NULL;
155 unsigned char *optr, *oend;
156 unsigned char *start = NULL; /* stupid initialize */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000157 size_t opt_len = 0; /* stupid initialize */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000158
159 int fd;
160 char *map;
161 int mapsize;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000162
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000163 if(fsize == 0) {
164 fprintf(stderr, "Warning: %s is empty\n", fname);
165 return;
166 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000167 fd = open(fname, O_RDONLY);
168 if(fd < 0) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000169 perror(fname);
170 return;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000171 }
172 mapsize = (fsize+pagesizem1) & ~pagesizem1;
173 map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
174 if ((long) map == -1)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000175 bb_error_d("%s: mmap: %m", fname);
176
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000177 optr = (unsigned char *)map;
178 oend = optr + fsize;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000179
180 line = 1;
181 called = state = S;
182
183 for(;;) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000184 if(prev_state != state) {
185 prev_state = state;
186 getc1();
187 }
188
189 /* [ \t]+ eat first space */
190 while(c == ' ' || c == '\t')
191 getc1();
192
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000193 if(c == BS) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000194 getc1();
195 if(c == '\n') {
196 /* \\\n eat continued */
197 line++;
198 prev_state = NLC;
199 continue;
200 }
201 ungetc1();
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000202 c = BS;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000203 }
204
205 if(state == S) {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000206 while(first_chars[c] == ANY) {
207 /* <S>unparsed */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000208 if(c == '\n')
209 line++;
210 getc1();
211 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000212 if(c == L_EOF) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000213 /* <S><<EOF>> */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000214 id_s = id;
215 mema_id = local_mema_id;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000216 munmap(map, mapsize);
217 close(fd);
218 return;
219 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000220 if(c == REM) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000221 /* <S>/ */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000222 getc1(); /* eat <S>/ */
223 if(c == REM) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000224 /* <S>"//"[^\n]* */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000225 do getc1(); while(c != '\n' && c != L_EOF);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000226 } else if(c == '*') {
227 /* <S>[/][*] */
228 called = S;
229 state = REM;
230 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000231 } else if(c == POUND) {
232 /* <S># */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000233 start = optr - 1;
234 state = c;
235 } else if(c == STR || c == CHR) {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000236 /* <S>\"|\' */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000237 val = NULL;
238 called = S;
239 state = c;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000240 } else if(c != BS) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000241 /* <S>[A-Z_a-z0-9] */
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000242
243 /* trick for fast drop id
244 if key with this first char undefined */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000245 if(first_chars[c] == 0) {
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000246 /* skip <S>[A-Z_a-z0-9]+ */
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000247 do getc1(); while(isalnums[c]);
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000248 } else {
249 id_len = 0;
250 do {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000251 /* <S>[A-Z_a-z0-9]+ */
252 put_id(c);
253 getc1();
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000254 } while(isalnums[c]);
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000255 check_key(key_top, id, id_len);
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000256 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000257 } else {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000258 /* <S>\\ */
259 prev_state = c;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000260 }
261 continue;
262 }
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++;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000272 } else if(c == L_EOF)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000273 yy_error_d("unexpected EOF");
274 getc1();
275 }
276 /* <REM>[*] */
277 getc1();
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000278 if(c == REM) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000279 /* <REM>[*][/] */
280 state = called;
281 break;
282 }
283 }
284 continue;
285 }
286 if(state == STR || state == CHR) {
287 for(;;) {
288 /* <STR,CHR>\n|<<EOF>> */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000289 if(c == '\n' || c == L_EOF)
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000290 yy_error_d("unterminated");
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000291 if(c == BS) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000292 /* <STR,CHR>\\ */
293 getc1();
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000294 if(c != BS && c != '\n' && c != state) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000295 /* another usage \ in str or char */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000296 if(c == L_EOF)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000297 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>\' */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000310 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;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000319 break;
320 } else if(val)
321 put_id(c);
322 /* <STR,CHR>. */
323 getc1();
324 }
325 continue;
326 }
327
328 /* begin preprocessor states */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000329 if(c == L_EOF)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000330 yy_error_d("unexpected EOF");
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000331 if(c == REM) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000332 /* <#.*>/ */
333 getc1();
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000334 if(c == REM)
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000335 yy_error_d("detected // in preprocessor line");
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000336 if(c == '*') {
337 /* <#.*>[/][*] */
338 called = state;
339 state = REM;
340 continue;
341 }
342 /* hmm, #.*[/] */
343 yy_error_d("strange preprocessor line");
344 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000345 if(state == POUND) {
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000346 /* tricks */
347 static const char * const preproc[] = {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000348 /* 0-3 */
349 "", "", "", "",
350 /* 4 */ /* 5 */ /* 6 */
351 "ndef", "efine", "nclude",
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000352 };
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000353 size_t diu = first_chars_diu[c]; /* strlen and preproc ptr */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000354 const unsigned char *p = optr;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000355
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000356 while(isalnums[c]) getc1();
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000357 /* have str begined with c, readed == strlen key and compared */
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000358 if(diu != S && diu == (optr-p-1) && !memcmp(p, preproc[diu], diu)) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000359 state = p[-1];
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000360 id_len = 0; /* common for save */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000361 } else {
362 state = S;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000363 }
364 ungetc1();
365 continue;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000366 }
367 if(state == I) {
368 if(c == STR) {
369 /* <I>\" */
370 val = id;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000371 called = LI;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000372 state = STR;
373 } else {
374 /* another (may be wrong) #include ... */
375 ungetc1();
376 state = S;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000377 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000378 continue;
379 }
380 if(state == D || state == U) {
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000381 if(mode == SOURCES_MODE) {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000382 /* ignore depend with #define or #undef KEY */
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000383 while(isalnums[c])
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000384 getc1();
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000385 state = S;
386 } else {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000387 /* save KEY from #"define"|"undef" ... */
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000388 while(isalnums[c]) {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000389 put_id(c);
390 getc1();
391 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000392 if(!id_len)
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000393 yy_error_d("expected identifier");
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000394 if(state == U) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000395 parse_conf_opt(id, NULL, (optr - start), id_len);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000396 state = S;
397 } else {
398 /* D -> DK */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000399 opt_len = id_len;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000400 state = DK;
401 }
402 }
403 ungetc1();
404 continue;
405 }
406 if(state == DK) {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000407 /* #define KEY[ ] (config mode) */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000408 val = id + id_len;
409 if(c == STR || c == CHR) {
410 /* define KEY "... or define KEY '... */
411 put_id(c);
412 called = DV;
413 state = c;
414 continue;
415 }
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000416 while(isalnums[c]) {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000417 /* VALUE */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000418 put_id(c);
419 getc1();
420 }
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000421 put_id(0);
422 parse_conf_opt(id, val, (optr - start), opt_len);
423 state = S;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000424 ungetc1();
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000425 continue;
426 }
427 }
428}
429
430
431static void show_usage(void) __attribute__ ((noreturn));
432static void show_usage(void)
433{
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000434 bb_error_d("%s\n%s\n", bb_mkdep_terse_options, bb_mkdep_full_options);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000435}
436
437static const char *kp;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000438static size_t kp_len;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000439static llist_t *Iop;
440static bb_key_t *Ifound;
441static int noiwarning;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000442
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000443static bb_key_t *check_key(bb_key_t *k, const char *nk, size_t key_sz)
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000444{
445 bb_key_t *cur;
446
447 for(cur = k; cur; cur = cur->next) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000448 if(key_sz == cur->key_sz && memcmp(cur->keyname, nk, key_sz) == 0) {
449 cur->checked = cur->stored_path;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000450 return cur;
451 }
452 }
453 return NULL;
454}
455
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000456static bb_key_t *make_new_key(bb_key_t *k, const char *nk, size_t key_sz)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000457{
458 bb_key_t *cur;
459
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000460 cur = xmalloc(sizeof(bb_key_t) + key_sz + 1);
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;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000465 cur->next = k;
466 return cur;
467}
468
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000469static inline char *store_include_fullpath(char *p_i, bb_key_t *li)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000470{
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000471 char *ok;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000472
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000473 if(access(p_i, F_OK) == 0) {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000474 ok = li->stored_path = bb_simplify_path(p_i);
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000475 li->checked = ok;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000476 } else {
477 ok = NULL;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000478 }
479 free(p_i);
480 return ok;
481}
482
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000483static void parse_inc(const char *include, const char *fname, size_t key_sz)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000484{
485 bb_key_t *li;
486 char *p_i;
487 llist_t *lo;
488
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000489 li = check_key(Ifound, include, key_sz);
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000490 if(li)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000491 return;
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000492 Ifound = li = make_new_key(Ifound, include, key_sz);
493 include = li->keyname;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000494 if(include[0] != '/') {
495 /* relative */
496 int w;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000497
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000498 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);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000502 if(store_include_fullpath(p_i, li))
503 return;
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000504 /* find from "-I include" specified directories */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000505 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) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000513 li->checked = li->stored_path = bb_xstrdup(include);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000514 return;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000515 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000516 }
517 li->stored_path = NULL;
518 if(noiwarning)
519 fprintf(stderr, "%s: Warning: #include \"%s\" not found in specified paths\n", fname, include);
520}
521
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000522static void parse_conf_opt(const char *opt, const char *val,
523 size_t recordsz, size_t key_sz)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000524{
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000525 bb_key_t *cur;
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000526 char *k;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000527 char *s, *p;
528 struct stat st;
529 int fd;
530 int cmp_ok = 0;
531 static char *record_buf;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000532 static size_t r_sz;
533 ssize_t rw_ret;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000534
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000535 cur = check_key(key_top, opt, key_sz);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000536 if(cur != NULL) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000537 /* present already */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000538 cur->checked = NULL; /* store only */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000539 if(cur->value == NULL && val == NULL)
540 return;
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000541 if(cur->value != NULL && val != NULL && !strcmp(cur->value, val))
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000542 return;
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000543 k = cur->keyname;
544 fprintf(stderr, "Warning: redefined %s\n", k);
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000545 } else {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000546 key_top = cur = make_new_key(key_top, opt, key_sz);
547 k = cur->keyname;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000548 }
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000549 /* do generate record */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000550 recordsz += 2; /* \n\0 */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000551 if(recordsz > r_sz)
552 record_buf = xrealloc(record_buf, (r_sz = recordsz) * 2);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000553 s = record_buf;
554 /* may be short count " " */
555 if(val) {
556 if(*val == '\0') {
557 cur->value = "";
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000558 recordsz = sprintf(s, "#define %s\n", k);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000559 } else {
560 cur->value = bb_xstrdup(val);
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000561 recordsz = sprintf(s, "#define %s %s\n", k, val);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000562 }
563 } else {
564 cur->value = NULL;
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000565 recordsz = sprintf(s, "#undef %s\n", k);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000566 }
567 /* size_t -> ssize_t :( */
568 rw_ret = (ssize_t)recordsz;
569 /* trick, save first char KEY for do fast identify id */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000570 first_chars[(int)*k] = *k;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000571
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000572 cur->stored_path = k = bb_asprint("%s/%s.h", kp, k);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000573 /* key converting [A-Z_] -> [a-z/] */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000574 for(p = k + kp_len + 1; *p; p++) {
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000575 if(*p >= 'A' && *p <= 'Z')
576 *p = *p - 'A' + 'a';
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000577 else if(*p == '_' && p[1] > '9') /* do not change A_1 to A/1 */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000578 *p = '/';
579 }
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000580 /* check kp/key.h if present after previous usage */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000581 if(stat(k, &st)) {
582 for(p = k + kp_len + 1; *p; p++) {
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000583 /* Auto-create directories. */
584 if (*p == '/') {
585 *p = '\0';
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000586 if (access(k, F_OK) != 0 && mkdir(k, 0755) != 0)
587 bb_error_d("mkdir(%s): %m", k);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000588 *p = '/';
589 }
590 }
591 } else {
592 /* found */
593 if(st.st_size == (off_t)recordsz) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000594 char *r_cmp = s + recordsz;
595
596 fd = open(k, O_RDONLY);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000597 if(fd < 0 || read(fd, r_cmp, recordsz) < rw_ret)
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000598 bb_error_d("%s: %m", k);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000599 close(fd);
600 cmp_ok = memcmp(s, r_cmp, recordsz) == 0;
601 }
602 }
603 if(!cmp_ok) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000604 fd = open(k, O_WRONLY|O_CREAT|O_TRUNC, 0644);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000605 if(fd < 0 || write(fd, s, recordsz) < rw_ret)
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000606 bb_error_d("%s: %m", k);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000607 close(fd);
608 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000609}
610
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000611static char *pwd;
612
613static int show_dep(int first, bb_key_t *k, const char *name, const char *f)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000614{
615 bb_key_t *cur;
616
617 for(cur = k; cur; cur = cur->next) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000618 if(cur->checked) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000619 if(first) {
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000620 if(f == NULL)
621 printf("\n%s:", name);
622 else
623 printf("\n%s/%s:", pwd, name);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000624 first = 0;
625 } else {
626 printf(" \\\n ");
627 }
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000628 printf(" %s", cur->checked);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000629 }
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000630 cur->checked = NULL;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000631 }
632 return first;
633}
634
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000635static size_t replace;
"Vladimir N. Oleynik"d5f2a182005-10-06 14:47:16 +0000636
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000637static struct stat st_kp;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000638static int dontgenerate_dep;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000639
640static char *
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000641parse_chd(const char *fe, const char *p, size_t dirlen)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000642{
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000643 struct stat st;
644 char *fp;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000645 size_t df_sz;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000646 static char *dir_and_entry;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000647 static size_t dir_and_entry_sz;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000648
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000649 df_sz = dirlen + strlen(fe) + 2; /* dir/file\0 */
650 if(df_sz > dir_and_entry_sz)
651 dir_and_entry = xrealloc(dir_and_entry, dir_and_entry_sz = df_sz);
652 fp = dir_and_entry;
653 sprintf(fp, "%s/%s", p, fe);
654
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000655 if(stat(fp, &st)) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000656 fprintf(stderr, "Warning: stat(%s): %m\n", fp);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000657 return NULL;
658 }
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000659 if(S_ISREG(st.st_mode)) {
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000660 llist_t *cfl;
661 char *e = fp + df_sz - 3;
662
663 if(*e++ != '.' || (*e != 'c' && *e != 'h')) {
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000664 /* direntry is regular file, but is not *.[ch] */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000665 return NULL;
666 }
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000667 for(cfl = configs; cfl; cfl = cfl->link) {
668 struct stat *config = (struct stat *)cfl->data;
669
670 if (st.st_dev == config->st_dev && st.st_ino == config->st_ino) {
671 /* skip already parsed configs.h */
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000672 return NULL;
673 }
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000674 }
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000675 /* direntry is *.[ch] regular file and is not configs */
676 if(!dontgenerate_dep) {
677 int first;
678
679 c_lex(fp, st.st_size);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000680 if(*e == 'c') {
681 /* *.c -> *.o */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000682 *e = 'o';
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000683 /* /src_dir/path/file.o to path/file.o */
684 fp += replace;
685 if(*fp == '/')
686 fp++;
"Vladimir N. Oleynik"d5f2a182005-10-06 14:47:16 +0000687 } else {
688 e = NULL;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000689 }
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000690 first = show_dep(1, Ifound, fp, e);
691 first = show_dep(first, key_top, fp, e);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000692 if(first == 0)
693 putchar('\n');
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000694 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000695 return NULL;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000696 } else if(S_ISDIR(st.st_mode)) {
697 if (st.st_dev == st_kp.st_dev && st.st_ino == st_kp.st_ino)
698 return NULL; /* drop scan kp/ directory */
699 /* direntry is directory. buff is returned, begin of zero allocate */
700 dir_and_entry = NULL;
701 dir_and_entry_sz = 0;
702 return fp;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000703 }
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000704 /* hmm, direntry is device! */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000705 return NULL;
706}
707
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000708/* from libbb but inline for fast */
709static inline llist_t *llist_add_to(llist_t *old_head, char *new_item)
710{
711 llist_t *new_head;
712
713 new_head = xmalloc(sizeof(llist_t));
714 new_head->data = new_item;
715 new_head->link = old_head;
716
717 return(new_head);
718}
719
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000720static void scan_dir_find_ch_files(const char *p)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000721{
722 llist_t *dirs;
723 llist_t *d_add;
724 llist_t *d;
725 struct dirent *de;
726 DIR *dir;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000727 size_t dirlen;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000728
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000729 dirs = llist_add_to(NULL, bb_simplify_path(p));
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000730 replace = strlen(dirs->data);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000731 /* emulate recursive */
732 while(dirs) {
733 d_add = NULL;
734 while(dirs) {
735 dir = opendir(dirs->data);
736 if (dir == NULL)
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000737 fprintf(stderr, "Warning: opendir(%s): %m\n", dirs->data);
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000738 dirlen = strlen(dirs->data);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000739 while ((de = readdir(dir)) != NULL) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000740 char *found_dir;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000741
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000742 if (de->d_name[0] == '.')
743 continue;
744 found_dir = parse_chd(de->d_name, dirs->data, dirlen);
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000745 if(found_dir)
746 d_add = llist_add_to(d_add, found_dir);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000747 }
748 closedir(dir);
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000749 free(dirs->data);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000750 d = dirs;
751 dirs = dirs->link;
752 free(d);
753 }
754 dirs = d_add;
755 }
756}
757
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000758
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000759int main(int argc, char **argv)
760{
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000761 char *s;
762 int i;
763 llist_t *fl;
764
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000765 {
766 /* for bb_simplify_path */
767 /* libbb xgetcwd(), this program have not chdir() */
768 unsigned path_max = 512;
769
770 s = xmalloc (path_max);
771#define PATH_INCR 32
772 while (getcwd (s, path_max) == NULL) {
773 if(errno != ERANGE)
774 bb_error_d("getcwd: %m");
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000775 s = xrealloc (s, path_max += PATH_INCR);
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000776 }
777 pwd = s;
778 }
779
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000780 while ((i = getopt(argc, argv, "I:c:dk:w")) > 0) {
781 switch(i) {
782 case 'I':
783 Iop = llist_add_to(Iop, optarg);
784 break;
785 case 'c':
786 s = bb_simplify_path(optarg);
787 configs = llist_add_to(configs, s);
788 break;
789 case 'd':
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000790 dontgenerate_dep = 1;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000791 break;
792 case 'k':
793 if(kp)
794 bb_error_d("Hmm, why multiple -k?");
795 kp = bb_simplify_path(optarg);
796 break;
797 case 'w':
798 noiwarning = 1;
799 break;
800 default:
801 show_usage();
802 }
803 }
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000804 /* default kp */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000805 if(kp == NULL)
806 kp = bb_simplify_path(INCLUDE_CONFIG_PATH);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000807 /* globals initialize */
808 kp_len = strlen(kp);
809 if(stat(kp, &st_kp))
810 bb_error_d("stat(%s): %m", kp);
811 if(!S_ISDIR(st_kp.st_mode))
812 bb_error_d("%s is not directory", kp);
813 /* defaults */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000814 if(Iop == NULL)
815 Iop = llist_add_to(Iop, LOCAL_INCLUDE_PATH);
816 if(configs == NULL) {
817 s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH);
818 configs = llist_add_to(configs, s);
819 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000820 /* for c_lex */
821 pagesizem1 = getpagesize() - 1;
822 id_s = xmalloc(mema_id);
823 for(i = 0; i < 256; i++) {
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000824 if(ISALNUM(i))
825 isalnums[i] = i;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000826 /* set unparsed chars for speed up of parser */
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000827 else if(i != CHR && i != STR && i != POUND && i != REM && i != BS)
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000828 first_chars[i] = ANY;
829 }
830 first_chars[i] = '-'; /* L_EOF */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000831
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000832 /* parse configs */
833 for(fl = configs; fl; fl = fl->link) {
834 struct stat st;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000835
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000836 if(stat(fl->data, &st))
837 bb_error_d("stat(%s): %m", fl->data);
838 c_lex(fl->data, st.st_size);
839 /* trick for fast comparing found files with configs */
840 fl->data = xrealloc(fl->data, sizeof(struct stat));
841 memcpy(fl->data, &st, sizeof(struct stat));
842 }
843
844 /* main loop */
845 mode = SOURCES_MODE;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000846 argv += optind;
847 if(*argv) {
848 while(*argv)
849 scan_dir_find_ch_files(*argv++);
850 } else {
851 scan_dir_find_ch_files(".");
852 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000853 return 0;
854}
855
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000856/* partial and simplified libbb routine */
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000857static void bb_error_d(const char *s, ...)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000858{
859 va_list p;
860
861 va_start(p, s);
862 vfprintf(stderr, s, p);
863 va_end(p);
864 putc('\n', stderr);
865 exit(1);
866}
867
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000868static char *bb_asprint(const char *format, ...)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000869{
870 va_list p;
871 int r;
872 char *out;
873
874 va_start(p, format);
875 r = vasprintf(&out, format, p);
876 va_end(p);
877
878 if (r < 0)
879 bb_error_d("bb_asprint: %m");
880 return out;
881}
882
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000883/* partial libbb routine as is */
884static void *xmalloc(size_t size)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000885{
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000886 void *p = malloc(size);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000887
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000888 if(p == NULL)
889 bb_error_d(msg_enomem);
890 return p;
891}
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000892
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000893static 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;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000898}
899
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000900static char *bb_xstrdup(const char *s)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000901{
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000902 char *r = strdup(s);
903
904 if(r == NULL)
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000905 bb_error_d(msg_enomem);
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000906 return r;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000907}
908
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000909static char *bb_simplify_path(const char *path)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000910{
911 char *s, *start, *p;
912
913 if (path[0] == '/')
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000914 start = bb_xstrdup(path);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000915 else {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000916 /* is not libbb, but this program have not chdir() */
917 start = bb_asprint("%s/%s", pwd, path);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000918 }
919 p = s = start;
920
921 do {
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000922 if (*p == '/') {
923 if (*s == '/') { /* skip duplicate (or initial) slash */
924 continue;
925 } else if (*s == '.') {
926 if (s[1] == '/' || s[1] == 0) { /* remove extra '.' */
927 continue;
928 } else if ((s[1] == '.') && (s[2] == '/' || s[2] == 0)) {
929 ++s;
930 if (p > start) {
931 while (*--p != '/'); /* omit previous dir */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000932 }
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000933 continue;
934 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000935 }
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000936 }
937 *++p = *s;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000938 } while (*++s);
939
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000940 if ((p == start) || (*p != '/')) { /* not a trailing slash */
941 ++p; /* so keep last character */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000942 }
943 *p = 0;
944
945 return start;
946}