blob: 758b78cb96db863c5e5dec7e7d34d88e0e73073b [file] [log] [blame]
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +00001/*
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +00002 * Another fast dependencies generator for Makefiles, Version 3.0
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +00003 *
4 * Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru>
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +00005 *
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +00006 * mmaping file may be originally by Linus Torvalds.
7 *
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +00008 * 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 *
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +000018 * (c) 2005 Bernhard Fischer:
19 * - commentary typos,
20 * - move "memory exhausted" into msg_enomem,
21 * - more verbose --help output.
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000022 *
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000023 * This program does:
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000024 * 1) find #define KEY VALUE or #undef KEY from include/config.h
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +000025 * 2) 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
27 * 4) generate dependencies to stdout
"Vladimir N. Oleynik"664c6e72005-10-06 14:53:43 +000028 * pwd/file.o: include/config/key*.h found_include_*.h
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000029 * path/inc.h: include/config/key*.h found_included_include_*.h
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +000030 * 5) save include/config/key*.h if changed after previous usage
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +000031 * This program does not generate dependencies for #include <...>
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000032 */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000033
34#define LOCAL_INCLUDE_PATH "include"
35#define INCLUDE_CONFIG_PATH LOCAL_INCLUDE_PATH"/config"
36#define INCLUDE_CONFIG_KEYS_PATH LOCAL_INCLUDE_PATH"/config.h"
37
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000038#define bb_mkdep_full_options \
39"\nOptions:" \
40"\n\t-I local_include_path include paths, default: \"" LOCAL_INCLUDE_PATH "\"" \
41"\n\t-d don't generate depend" \
42"\n\t-w show warning if include files not found" \
43"\n\t-k include/config default: \"" INCLUDE_CONFIG_PATH "\"" \
44"\n\t-c include/config.h configs, default: \"" INCLUDE_CONFIG_KEYS_PATH "\"" \
45"\n\tdirs_to_scan default \".\""
46
47#define bb_mkdep_terse_options "Usage: [-I local_include_paths] [-dw] " \
48 "[-k path_for_stored_keys] [dirs]"
49
50
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000051#define _GNU_SOURCE
52#include <sys/types.h>
53#include <sys/stat.h>
54#include <sys/mman.h>
55#include <getopt.h>
56#include <dirent.h>
57#include <stdio.h>
58#include <stdlib.h>
59#include <string.h>
60#include <stdarg.h>
61#include <unistd.h>
62#include <errno.h>
63#include <fcntl.h>
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +000064#include <limits.h>
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000065
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000066
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000067/* partial and simplified libbb routine */
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +000068static void bb_error_d(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
69static char * bb_asprint(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +000070static char *bb_simplify_path(const char *path);
"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"083d3f42005-10-10 11:35:17 +000077
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +000078static const char msg_enomem[] = "memory exhausted";
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +000079
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +000080/* inline realization for fast works */
81static inline void *xmalloc(size_t size)
82{
83 void *p = malloc(size);
84
85 if(p == NULL)
86 bb_error_d(msg_enomem);
87 return p;
88}
89
90static inline char *bb_xstrdup(const char *s)
91{
92 char *r = strdup(s);
93
94 if(r == NULL)
95 bb_error_d(msg_enomem);
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
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000142/* for lexical analyser */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000143static int pagesizem1; /* padding mask = getpagesize() - 1 */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000144
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000145/* for speed tricks */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000146static char first_chars[1+UCHAR_MAX]; /* + L_EOF */
147static char isalnums[1+UCHAR_MAX]; /* + L_EOF */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000148/* trick for fast find "define", "include", "undef" */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000149static const char first_chars_diu[UCHAR_MAX] = {
150 [(int)'d'] = (char)5, /* strlen("define") - 1; */
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000151 [(int)'i'] = (char)6, /* strlen("include") - 1; */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000152 [(int)'u'] = (char)4, /* strlen("undef") - 1; */
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000153};
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000154
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000155#define CONFIG_MODE 0
156#define SOURCES_MODE 1
157static int mode;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000158
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000159#define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s)
160
161/* state */
162#define S 0 /* start state */
163#define STR '"' /* string */
164#define CHR '\'' /* char */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000165#define REM '/' /* block comment */
166#define BS '\\' /* back slash */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000167#define POUND '#' /* # */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000168#define D '5' /* #define preprocessor's directive */
169#define I '6' /* #include preprocessor's directive */
170#define U '4' /* #undef preprocessor's directive */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000171#define DK 'K' /* #define KEY... (config mode) */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000172#define ANY '*' /* any unparsed chars */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000173
174/* [A-Z_a-z] */
175#define ID(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_')
176/* [A-Z_a-z0-9] */
177#define ISALNUM(c) (ID(c) || (c >= '0' && c <= '9'))
178
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000179#define L_EOF (1+UCHAR_MAX)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000180
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000181#define getc0() do { c = (optr >= oend) ? L_EOF : *optr++; } while(0)
182
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)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000191
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000192
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000193/* stupid C lexical analyser */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000194static void c_lex(const char *fname, long fsize)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000195{
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000196 int c;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000197 int state;
198 int line;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000199 char *id = id_s;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000200 size_t id_len = 0; /* stupid initialize */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000201 unsigned char *optr, *oend;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000202
203 int fd;
204 char *map;
205 int mapsize;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000206
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000207 if(fsize == 0) {
208 fprintf(stderr, "Warning: %s is empty\n", fname);
209 return;
210 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000211 fd = open(fname, O_RDONLY);
212 if(fd < 0) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000213 perror(fname);
214 return;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000215 }
216 mapsize = (fsize+pagesizem1) & ~pagesizem1;
217 map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
218 if ((long) map == -1)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000219 bb_error_d("%s: mmap: %m", fname);
220
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000221 optr = (unsigned char *)map;
222 oend = optr + fsize;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000223
224 line = 1;
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000225 state = S;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000226
227 for(;;) {
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000228 getc1();
229 for(;;) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000230 /* [ \t]+ eat first space */
231 while(c == ' ' || c == '\t')
232 getc1();
233
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000234 if(state == S) {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000235 while(first_chars[c] == ANY) {
236 /* <S>unparsed */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000237 if(c == '\n')
238 line++;
239 getc1();
240 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000241 if(c == L_EOF) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000242 /* <S><<EOF>> */
243 munmap(map, mapsize);
244 close(fd);
245 return;
246 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000247 if(c == REM) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000248 /* <S>/ */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000249 getc0();
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000250 if(c == REM) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000251 /* <S>"//"[^\n]* */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000252 do getc0(); while(c != '\n' && c != L_EOF);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000253 } else if(c == '*') {
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000254 /* <S>[/][*] goto parse block comments */
255 break;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000256 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000257 } else if(c == POUND) {
258 /* <S># */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000259 state = c;
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000260 getc1();
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000261 } else if(c == STR || c == CHR) {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000262 /* <S>\"|\' */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000263 int qc = c;
264
265 for(;;) {
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 {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000281 /* <S>[A-Z_a-z0-9] */
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000282
283 /* trick for fast drop id
284 if key with this first char undefined */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000285 if(first_chars[c] == 0) {
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000286 /* skip <S>[A-Z_a-z0-9]+ */
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000287 do getc1(); while(isalnums[c]);
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000288 } else {
289 id_len = 0;
290 do {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000291 /* <S>[A-Z_a-z0-9]+ */
292 put_id(c);
293 getc1();
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000294 } while(isalnums[c]);
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000295 check_key(key_top, id, id_len);
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000296 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000297 }
298 continue;
299 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000300 /* begin preprocessor states */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000301 if(c == L_EOF)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000302 yy_error_d("unexpected EOF");
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000303 if(c == REM) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000304 /* <#.*>/ */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000305 getc0();
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000306 if(c == REM)
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000307 yy_error_d("detected // in preprocessor line");
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000308 if(c == '*') {
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000309 /* <#.*>[/][*] goto parse block comments */
310 break;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000311 }
312 /* hmm, #.*[/] */
313 yy_error_d("strange preprocessor line");
314 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000315 if(state == POUND) {
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000316 /* tricks */
317 static const char * const preproc[] = {
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000318 /* 0 1 2 3 4 5 6 */
319 "", "", "", "", "ndef", "efine", "nclude"
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000320 };
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000321 size_t diu = first_chars_diu[c]; /* strlen and preproc ptr */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000322
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000323 state = S;
324 if(diu != S) {
325 getc1();
326 id_len = 0;
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 }
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000336 } else {
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000337 while(isalnums[c]) getc1();
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000338 }
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000339 } else if(state == I) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000340 if(c == STR) {
341 /* <I>\" */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000342 for(;;) {
343 getc1();
344 if(c == STR)
345 break;
346 if(c == L_EOF)
347 yy_error_d("unexpected EOF");
348 put_id(c);
349 }
350 put_id(0);
351 /* store "include.h" */
352 parse_inc(id, fname);
353 getc1();
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000354 }
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000355 /* else another (may be wrong) #include ... */
356 state = S;
357 } else if(state == D || state == U) {
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000358 if(mode == SOURCES_MODE) {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000359 /* ignore depend with #define or #undef KEY */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000360 while(isalnums[c]) getc1();
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000361 state = S;
362 } else {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000363 /* save KEY from #"define"|"undef" ... */
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000364 while(isalnums[c]) {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000365 put_id(c);
366 getc1();
367 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000368 if(!id_len)
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000369 yy_error_d("expected identifier");
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000370 if(state == U) {
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000371 parse_conf_opt(id, NULL, id_len);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000372 state = S;
373 } else {
374 /* D -> DK */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000375 if(c == '(')
376 yy_error_d("unexpected function macro");
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000377 state = DK;
378 }
379 }
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000380 } else {
381 /* state==<DK> #define KEY[ ] (config mode) */
382 size_t opt_len = id_len;
383 char *val = id + opt_len;
384 char *sp;
385
386 for(;;) {
387 if(c == L_EOF || c == '\n')
388 break;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000389 put_id(c);
390 getc1();
391 }
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000392 sp = id + id_len;
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000393 put_id(0);
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000394 /* 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);
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000399 state = S;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000400 }
401 }
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000402
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");
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000427}
428
429
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000430/* bb_simplify_path special variant for apsolute pathname */
431static size_t bb_qa_simplify_path(char *path)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000432{
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000433 char *s, *p;
434
435 p = s = path;
436
437 do {
438 if (*p == '/') {
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);
455
456 if ((p == path) || (*p != '/')) { /* not a trailing slash */
457 ++p; /* so keep last character */
458 }
459 *p = 0;
460
461 return (p - path);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000462}
463
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000464static void parse_inc(const char *include, const char *fname)
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000465{
466 bb_key_t *cur;
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000467 const char *p_i;
468 llist_t *lo;
469 char *ap;
470 size_t key_sz;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000471
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000472 if(*include == '/') {
473 lo = NULL;
474 ap = bb_xstrdup(include);
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000475 } else {
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000476 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);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000484 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000485
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000486 for(;;) {
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);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000492 return;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000493 }
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000494 if(access(ap, F_OK) == 0) {
495 /* found */
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;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000519}
520
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000521static size_t max_rec_sz;
522
523static void parse_conf_opt(const char *opt, const char *val, 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"083d3f42005-10-10 11:35:17 +0000527 char *p;
528 size_t val_sz = 0;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000529
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000530 cur = check_key(key_top, opt, key_sz);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000531 if(cur != NULL) {
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000532 /* present already */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000533 cur->checked = NULL; /* store only */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000534 if(cur->value == NULL && val == NULL)
535 return;
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000536 if(cur->value != NULL && val != NULL && !strcmp(cur->value, val))
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000537 return;
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000538 k = cur->keyname;
539 fprintf(stderr, "Warning: redefined %s\n", k);
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000540 } else {
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000541 size_t recordsz;
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;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000556 }
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000557 /* save VAL */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000558 if(val) {
559 if(*val == '\0') {
560 cur->value = "";
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000561 } else {
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000562 cur->value = p = cur->keyname + key_sz + 1;
563 memcpy(p, val, val_sz);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000564 }
565 } else {
566 cur->value = NULL;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000567 }
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000568 /* trick, save first char KEY for do fast identify id */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000569 first_chars[(int)*k] = *k;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000570
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000571 cur->stored_path = k = bb_asprint("%s/%s.h", kp, k);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000572 /* key converting [A-Z_] -> [a-z/] */
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000573 for(p = k + kp_len + 1; *p; p++) {
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000574 if(*p >= 'A' && *p <= 'Z')
575 *p = *p - 'A' + 'a';
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000576 else if(*p == '_' && p[1] > '9') /* do not change A_1 to A/1 */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000577 *p = '/';
578 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000579}
580
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000581static void store_keys(void)
582{
583 bb_key_t *cur;
584 char *k;
585 struct stat st;
586 int cmp_ok;
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);
604 }
605 }
606 /* size_t -> ssize_t :( */
607 rw_ret = (ssize_t)recordsz;
608 /* check kp/key.h, compare after previous usage */
609 cmp_ok = 0;
610 k = cur->stored_path;
611 if(stat(k, &st)) {
612 char *p;
613 for(p = k + kp_len + 1; *p; p++) {
614 /* Auto-create directories. */
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 }
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 }
645 }
646 }
647}
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000648
649static int show_dep(int first, bb_key_t *k, const char *name, const char *f)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000650{
651 bb_key_t *cur;
652
653 for(cur = k; cur; cur = cur->next) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000654 if(cur->checked) {
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000655 if(first >= 0) {
656 if(first) {
657 if(f == NULL)
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000658 printf("\n%s:", name);
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000659 else
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000660 printf("\n%s/%s:", pwd, name);
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000661 first = 0;
662 } else {
663 printf(" \\\n ");
664 }
665 printf(" %s", cur->checked);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000666 }
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000667 cur->src_have_this_key = cur->checked;
668 cur->checked = NULL;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000669 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000670 }
671 return first;
672}
673
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000674static char *
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000675parse_chd(const char *fe, const char *p, size_t dirlen)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000676{
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000677 struct stat st;
678 char *fp;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000679 size_t df_sz;
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000680 static char dir_and_entry[4096];
681 size_t fe_sz = strlen(fe) + 1;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000682
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000683 df_sz = dirlen + fe_sz + 1; /* dir/file\0 */
684 if(df_sz > sizeof(dir_and_entry))
685 bb_error_d("%s: file name too long", fe);
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000686 fp = dir_and_entry;
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000687 /* sprintf(fp, "%s/%s", p, fe); */
688 memcpy(fp, p, dirlen);
689 fp[dirlen] = '/';
690 memcpy(fp + dirlen + 1, fe, fe_sz);
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000691
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000692 if(stat(fp, &st)) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000693 fprintf(stderr, "Warning: stat(%s): %m\n", fp);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000694 return NULL;
695 }
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000696 if(S_ISREG(st.st_mode)) {
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000697 llist_t *cfl;
698 char *e = fp + df_sz - 3;
699
700 if(*e++ != '.' || (*e != 'c' && *e != 'h')) {
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000701 /* direntry is regular file, but is not *.[ch] */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000702 return NULL;
703 }
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000704 for(cfl = configs; cfl; cfl = cfl->link) {
705 struct stat *config = (struct stat *)cfl->data;
706
707 if (st.st_dev == config->st_dev && st.st_ino == config->st_ino) {
708 /* skip already parsed configs.h */
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000709 return NULL;
710 }
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000711 }
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000712 /* direntry is *.[ch] regular file and is not configs */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000713 c_lex(fp, st.st_size);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000714 if(!dontgenerate_dep) {
715 int first;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000716 if(*e == 'c') {
717 /* *.c -> *.o */
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000718 *e = 'o';
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000719 /* /src_dir/path/file.o to path/file.o */
720 fp += replace;
721 if(*fp == '/')
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000722 fp++;
"Vladimir N. Oleynik"d5f2a182005-10-06 14:47:16 +0000723 } else {
724 e = NULL;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000725 }
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000726 first = show_dep(1, Ifound, fp, e);
727 first = show_dep(first, key_top, fp, e);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000728 if(first == 0)
729 putchar('\n');
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000730 } else {
731 show_dep(-1, key_top, NULL, NULL);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000732 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000733 return NULL;
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000734 } else if(S_ISDIR(st.st_mode)) {
735 if (st.st_dev == st_kp.st_dev && st.st_ino == st_kp.st_ino)
736 return NULL; /* drop scan kp/ directory */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000737 /* direntry is directory. buff is returned */
738 return bb_xstrdup(fp);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000739 }
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000740 /* hmm, direntry is device! */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000741 return NULL;
742}
743
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000744/* from libbb but inline for fast */
745static inline llist_t *llist_add_to(llist_t *old_head, char *new_item)
746{
747 llist_t *new_head;
748
749 new_head = xmalloc(sizeof(llist_t));
750 new_head->data = new_item;
751 new_head->link = old_head;
752
753 return(new_head);
754}
755
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000756static void scan_dir_find_ch_files(const char *p)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000757{
758 llist_t *dirs;
759 llist_t *d_add;
760 llist_t *d;
761 struct dirent *de;
762 DIR *dir;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000763 size_t dirlen;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000764
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000765 dirs = llist_add_to(NULL, bb_simplify_path(p));
"Vladimir N. Oleynik"6c0642d2005-10-07 15:36:26 +0000766 replace = strlen(dirs->data);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000767 /* emulate recursive */
768 while(dirs) {
769 d_add = NULL;
770 while(dirs) {
771 dir = opendir(dirs->data);
772 if (dir == NULL)
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000773 fprintf(stderr, "Warning: opendir(%s): %m\n", dirs->data);
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000774 dirlen = strlen(dirs->data);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000775 while ((de = readdir(dir)) != NULL) {
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000776 char *found_dir;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000777
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000778 if (de->d_name[0] == '.')
779 continue;
780 found_dir = parse_chd(de->d_name, dirs->data, dirlen);
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000781 if(found_dir)
782 d_add = llist_add_to(d_add, found_dir);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000783 }
784 closedir(dir);
"Vladimir N. Oleynik"d128b712005-10-03 10:08:46 +0000785 free(dirs->data);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000786 d = dirs;
787 dirs = dirs->link;
788 free(d);
789 }
790 dirs = d_add;
791 }
792}
793
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000794static 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}
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000799
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000800int main(int argc, char **argv)
801{
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000802 char *s;
803 int i;
804 llist_t *fl;
805
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000806 {
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000807 /* for bb_simplify_path, this program have not chdir() */
808 /* libbb-like my xgetcwd() */
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000809 unsigned path_max = 512;
810
811 s = xmalloc (path_max);
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000812 while (getcwd (s, path_max) == NULL) {
813 if(errno != ERANGE)
814 bb_error_d("getcwd: %m");
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000815 free(s);
816 s = xmalloc(path_max *= 2);
817 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000818 pwd = s;
819 }
820
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000821 while ((i = getopt(argc, argv, "I:c:dk:w")) > 0) {
822 switch(i) {
823 case 'I':
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000824 s = bb_simplify_path(optarg);
825 Iop = llist_add_to(Iop, s);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000826 break;
827 case 'c':
828 s = bb_simplify_path(optarg);
829 configs = llist_add_to(configs, s);
830 break;
831 case 'd':
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000832 dontgenerate_dep = 1;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000833 break;
834 case 'k':
835 if(kp)
836 bb_error_d("Hmm, why multiple -k?");
837 kp = bb_simplify_path(optarg);
838 break;
839 case 'w':
840 noiwarning = 1;
841 break;
842 default:
843 show_usage();
844 }
845 }
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000846 /* default kp */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000847 if(kp == NULL)
848 kp = bb_simplify_path(INCLUDE_CONFIG_PATH);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000849 /* globals initialize */
850 kp_len = strlen(kp);
851 if(stat(kp, &st_kp))
852 bb_error_d("stat(%s): %m", kp);
853 if(!S_ISDIR(st_kp.st_mode))
854 bb_error_d("%s is not directory", kp);
855 /* defaults */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000856 if(Iop == NULL)
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000857 Iop = llist_add_to(Iop, bb_simplify_path(LOCAL_INCLUDE_PATH));
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000858 if(configs == NULL) {
859 s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH);
860 configs = llist_add_to(configs, s);
861 }
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000862 /* for c_lex */
863 pagesizem1 = getpagesize() - 1;
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000864 for(i = 0; i < UCHAR_MAX; i++) {
"Vladimir N. Oleynik"af0dd592005-09-16 13:57:33 +0000865 if(ISALNUM(i))
866 isalnums[i] = i;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000867 /* set unparsed chars for speed up of parser */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000868 else if(i != CHR && i != STR && i != POUND && i != REM)
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000869 first_chars[i] = ANY;
870 }
871 first_chars[i] = '-'; /* L_EOF */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000872
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000873 /* parse configs */
874 for(fl = configs; fl; fl = fl->link) {
875 struct stat st;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000876
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000877 if(stat(fl->data, &st))
878 bb_error_d("stat(%s): %m", fl->data);
879 c_lex(fl->data, st.st_size);
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000880 free(fl->data);
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000881 /* trick for fast comparing found files with configs */
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000882 fl->data = xmalloc(sizeof(struct stat));
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000883 memcpy(fl->data, &st, sizeof(struct stat));
884 }
885
886 /* main loop */
887 mode = SOURCES_MODE;
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000888 argv += optind;
889 if(*argv) {
890 while(*argv)
891 scan_dir_find_ch_files(*argv++);
892 } else {
893 scan_dir_find_ch_files(".");
894 }
"Vladimir N. Oleynik"083d3f42005-10-10 11:35:17 +0000895 store_keys();
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000896 return 0;
897}
898
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000899/* partial and simplified libbb routine */
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000900static void bb_error_d(const char *s, ...)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000901{
902 va_list p;
903
904 va_start(p, s);
905 vfprintf(stderr, s, p);
906 va_end(p);
907 putc('\n', stderr);
908 exit(1);
909}
910
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000911static char *bb_asprint(const char *format, ...)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000912{
913 va_list p;
914 int r;
915 char *out;
916
917 va_start(p, format);
918 r = vasprintf(&out, format, p);
919 va_end(p);
920
921 if (r < 0)
922 bb_error_d("bb_asprint: %m");
923 return out;
924}
925
"Vladimir N. Oleynik"7573ac62005-09-14 15:09:06 +0000926/* partial libbb routine as is */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000927
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000928static char *bb_simplify_path(const char *path)
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000929{
930 char *s, *start, *p;
931
932 if (path[0] == '/')
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000933 start = bb_xstrdup(path);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000934 else {
"Vladimir N. Oleynik"676e95e2005-09-13 16:50:53 +0000935 /* is not libbb, but this program have not chdir() */
936 start = bb_asprint("%s/%s", pwd, path);
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000937 }
938 p = s = start;
939
940 do {
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000941 if (*p == '/') {
942 if (*s == '/') { /* skip duplicate (or initial) slash */
943 continue;
944 } else if (*s == '.') {
945 if (s[1] == '/' || s[1] == 0) { /* remove extra '.' */
946 continue;
947 } else if ((s[1] == '.') && (s[2] == '/' || s[2] == 0)) {
948 ++s;
949 if (p > start) {
950 while (*--p != '/'); /* omit previous dir */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000951 }
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000952 continue;
953 }
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000954 }
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000955 }
956 *++p = *s;
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000957 } while (*++s);
958
"Vladimir N. Oleynik"b1fe4622005-09-12 16:39:47 +0000959 if ((p == start) || (*p != '/')) { /* not a trailing slash */
960 ++p; /* so keep last character */
"Vladimir N. Oleynik"5e60dc42005-09-12 12:33:27 +0000961 }
962 *p = 0;
963
964 return start;
965}