diff options
author | Rob Landley <rob@landley.net> | 2006-02-13 19:16:41 +0000 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2006-02-13 19:16:41 +0000 |
commit | 7bfa88f315d71c7f7a1b76fcec3886c7506aca24 (patch) | |
tree | 5995ddbb62eeda3512fa408b78bbd1eb8832ae4a /scripts | |
parent | f251ec6847d28035ae42ad2c1ae94454d36c36d3 (diff) | |
download | busybox-w32-7bfa88f315d71c7f7a1b76fcec3886c7506aca24.tar.gz busybox-w32-7bfa88f315d71c7f7a1b76fcec3886c7506aca24.tar.bz2 busybox-w32-7bfa88f315d71c7f7a1b76fcec3886c7506aca24.zip |
New USE() macros
For each CONFIG_SYMBOL, include/bb_config.h now has both ENABLE_SYMBOL
and USE_SYMBOL(x). ENABLE_SYMBOL is still always defined (1 or 0) so that
if(ENABLE) should optimize out when it's zero. The USE_SYMBOL(X) will only
splice in X if the symbol is defined, otherwise it'll be empty.
Thus we can convert this:
#ifdef CONFIG_ARGS
opt = bb_getopt_ulflags(argc, argv, "ab:c"
#ifdef CONFIG_THINGY
"d:"
#endif
, &bvalue
#ifdef CONFIG_THINGY
, &thingy
#endif
);
#endif
into this:
if (ENABLE_ARGS) {
opt = bb_getopt_ulflags(argc, argv, "ab:c" USE_THINGY("d:"), &bvalue
USE_THINGY(, &thingy));
}
And it should produce the same code.
Unlike the old versions in include/_usage.h, the new USE_SYMBOL(x) can handle
commas in its arguments (as shown above). (The _usage.h file is obsolete and
no longer generated.)
Nobody should need to include config.h directly anymore, bb_config.h should
define all the configuration stuff we need. Someday, the CONFIG_SYMBOL
versions should go away in favor of ENABLE_SYMBOL and USE_SYMBOL().
Thanks to vodz for the new version of bb_mkdep.c that works with function
macros.
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/bb_mkdep.c | 931 |
1 files changed, 866 insertions, 65 deletions
diff --git a/scripts/bb_mkdep.c b/scripts/bb_mkdep.c index 3fea20aed..7219feef9 100644 --- a/scripts/bb_mkdep.c +++ b/scripts/bb_mkdep.c | |||
@@ -1,10 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * Another fast dependencies generator for Makefiles, Version 3.0 | 2 | * Another fast dependencies generator for Makefiles, Version 4.0 |
3 | * | 3 | * |
4 | * Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru> | 4 | * Copyright (C) 2005,2006 by Vladimir Oleynik <dzo@simtreas.ru> |
5 | * | 5 | * |
6 | * mmaping file may be originally by Linus Torvalds. | 6 | * mmaping file may be originally by Linus Torvalds. |
7 | * | 7 | * |
8 | * infix parser/evaluator for #if expression | ||
9 | * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com> | ||
10 | * Copyright (c) 2001 Manuel Novoa III <mjn3@codepoet.org> | ||
11 | * Copyright (c) 2003 Vladimir Oleynik <dzo@simtreas.ru> | ||
12 | * | ||
8 | * bb_simplify_path() | 13 | * bb_simplify_path() |
9 | * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org> | 14 | * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org> |
10 | * | 15 | * |
@@ -15,7 +20,7 @@ | |||
15 | * Copyright (C) 2003 Glenn McGrath | 20 | * Copyright (C) 2003 Glenn McGrath |
16 | * Copyright (C) Vladimir Oleynik <dzo@simtreas.ru> | 21 | * Copyright (C) Vladimir Oleynik <dzo@simtreas.ru> |
17 | * | 22 | * |
18 | * (c) 2005 Bernhard Fischer: | 23 | * (c) 2005,2006 Bernhard Fischer: |
19 | * - commentary typos, | 24 | * - commentary typos, |
20 | * - move "memory exhausted" into msg_enomem, | 25 | * - move "memory exhausted" into msg_enomem, |
21 | * - more verbose --help output. | 26 | * - more verbose --help output. |
@@ -29,6 +34,7 @@ | |||
29 | * path/inc.h: include/config/key*.h found_included_include_*.h | 34 | * path/inc.h: include/config/key*.h found_included_include_*.h |
30 | * 5) save include/config/key*.h if changed after previous usage | 35 | * 5) save include/config/key*.h if changed after previous usage |
31 | * This program does not generate dependencies for #include <...> | 36 | * This program does not generate dependencies for #include <...> |
37 | * Config file can have #if #elif #else #ifdef #ifndef #endif lines | ||
32 | */ | 38 | */ |
33 | 39 | ||
34 | #define LOCAL_INCLUDE_PATH "include" | 40 | #define LOCAL_INCLUDE_PATH "include" |
@@ -103,9 +109,9 @@ static llist_t *configs; /* list of -c usaged and them stat() after parsed */ | |||
103 | static llist_t *Iop; /* list of -I include usaged */ | 109 | static llist_t *Iop; /* list of -I include usaged */ |
104 | 110 | ||
105 | static char *pwd; /* current work directory */ | 111 | static char *pwd; /* current work directory */ |
106 | static size_t replace; /* replace current work directory with build dir */ | 112 | static size_t replace; /* replace current work derectory to build dir */ |
107 | 113 | ||
108 | static const char *kp; /* KEY path, argument of -k used */ | 114 | static const char *kp; /* KEY path, argument of -k usaged */ |
109 | static size_t kp_len; | 115 | static size_t kp_len; |
110 | static struct stat st_kp; /* stat(kp) */ | 116 | static struct stat st_kp; /* stat(kp) */ |
111 | 117 | ||
@@ -139,22 +145,44 @@ static inline bb_key_t *check_key(bb_key_t *k, const char *nk, size_t key_sz) | |||
139 | return NULL; | 145 | return NULL; |
140 | } | 146 | } |
141 | 147 | ||
148 | static inline const char *lookup_key(const char *nk, size_t key_sz) | ||
149 | { | ||
150 | bb_key_t *cur; | ||
151 | |||
152 | for(cur = key_top; cur; cur = cur->next) { | ||
153 | if(key_sz == cur->key_sz && memcmp(cur->keyname, nk, key_sz) == 0) { | ||
154 | return cur->value; | ||
155 | } | ||
156 | } | ||
157 | return NULL; | ||
158 | } | ||
159 | |||
142 | /* for lexical analyser */ | 160 | /* for lexical analyser */ |
143 | static int pagesizem1; /* padding mask = getpagesize() - 1 */ | 161 | static int pagesizem1; /* padding mask = getpagesize() - 1 */ |
144 | 162 | ||
145 | /* for speed tricks */ | 163 | /* for speed tricks */ |
146 | static char first_chars[1+UCHAR_MAX]; /* + L_EOF */ | 164 | static char first_chars[1+UCHAR_MAX]; /* + L_EOF */ |
147 | static char isalnums[1+UCHAR_MAX]; /* + L_EOF */ | 165 | static char isalnums[1+UCHAR_MAX]; /* + L_EOF */ |
148 | /* trick for fast find "define", "include", "undef" */ | 166 | |
149 | static const char first_chars_diu[UCHAR_MAX] = { | 167 | /* trick for fast find "define", "include", "undef", |
150 | [(int)'d'] = (char)5, /* strlen("define") - 1; */ | 168 | "if((n)def)" "else", "endif" */ |
151 | [(int)'i'] = (char)6, /* strlen("include") - 1; */ | 169 | static const char * const preproc[] = { |
152 | [(int)'u'] = (char)4, /* strlen("undef") - 1; */ | 170 | /* 0 1 2 3 4 5 6 7 8 9 */ |
171 | "", "efine", "lif", "lse", "ndif", "f", "fdef", "fndef", "nclude", "ndef" }; | ||
172 | static const unsigned char first_chars_deiu[UCHAR_MAX] = { | ||
173 | [(int)'d'] = (unsigned char)(1|0x10), /* define */ | ||
174 | [(int)'e'] = (unsigned char)(2|0x40), /* elif, else, endif */ | ||
175 | [(int)'i'] = (unsigned char)(5|0x80), /* if ifdef ifndef include */ | ||
176 | [(int)'u'] = (unsigned char)(9|0x90), /* undef */ | ||
153 | }; | 177 | }; |
154 | 178 | ||
155 | #define CONFIG_MODE 0 | 179 | #define CONFIG_MODE 0 |
156 | #define SOURCES_MODE 1 | 180 | #define IF0_MODE 1 /* #if 0 */ |
157 | static int mode; | 181 | #define IF1_MODE 2 /* #if 1 */ |
182 | #define ELSE0_MODE 4 /* #else found after #if 0 */ | ||
183 | #define ELSE1_MODE 8 /* #else found after #if 1 */ | ||
184 | #define ELIF1_MODE 16 /* #elif found after #if 1 */ | ||
185 | #define FALSE_MODES (IF0_MODE|ELSE1_MODE|ELIF1_MODE) | ||
158 | 186 | ||
159 | #define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s) | 187 | #define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s) |
160 | 188 | ||
@@ -165,9 +193,15 @@ static int mode; | |||
165 | #define REM '/' /* block comment */ | 193 | #define REM '/' /* block comment */ |
166 | #define BS '\\' /* back slash */ | 194 | #define BS '\\' /* back slash */ |
167 | #define POUND '#' /* # */ | 195 | #define POUND '#' /* # */ |
168 | #define D '5' /* #define preprocessor's directive */ | 196 | #define D '1' /* #define preprocessor's directive */ |
169 | #define I '6' /* #include preprocessor's directive */ | 197 | #define EI '2' /* #elif preprocessor's directive */ |
170 | #define U '4' /* #undef preprocessor's directive */ | 198 | #define E '3' /* #else preprocessor's directive */ |
199 | #define EF '4' /* #endif preprocessor's directive */ | ||
200 | #define F '5' /* #if preprocessor's directive */ | ||
201 | #define IFD '6' /* #ifdef preprocessor's directive */ | ||
202 | #define IFND '7' /* #ifndef preprocessor's directive */ | ||
203 | #define I '8' /* #include preprocessor's directive */ | ||
204 | #define U '9' /* #undef preprocessor's directive */ | ||
171 | #define DK 'K' /* #define KEY... (config mode) */ | 205 | #define DK 'K' /* #define KEY... (config mode) */ |
172 | #define ANY '*' /* any unparsed chars */ | 206 | #define ANY '*' /* any unparsed chars */ |
173 | 207 | ||
@@ -189,16 +223,508 @@ static char id_s[4096]; | |||
189 | #define put_id(ic) do { if(id_len == sizeof(id_s)) goto too_long; \ | 223 | #define put_id(ic) do { if(id_len == sizeof(id_s)) goto too_long; \ |
190 | id[id_len++] = ic; } while(0) | 224 | id[id_len++] = ic; } while(0) |
191 | 225 | ||
226 | static char ifcpp_stack[1024]; | ||
227 | static int ptr_ifcpp_stack; | ||
228 | #define push_mode() do { \ | ||
229 | if(ptr_ifcpp_stack == (int)sizeof(ifcpp_stack)) \ | ||
230 | yy_error_d("#if* stack overflow"); \ | ||
231 | ifcpp_stack[ptr_ifcpp_stack++] = (char)mode; \ | ||
232 | } while(0) | ||
233 | |||
234 | #define pop_mode() do { \ | ||
235 | if(ptr_ifcpp_stack == 0) \ | ||
236 | yy_error_d("unexpected #endif"); \ | ||
237 | mode = ifcpp_stack[--ptr_ifcpp_stack]; \ | ||
238 | } while(0) | ||
239 | |||
240 | /* #if expression */ | ||
241 | typedef long long arith_t; | ||
242 | |||
243 | static arith_t arith (const char *expr, int *perrcode); | ||
244 | |||
245 | /* The code uses a simple two-stack algorithm. See | ||
246 | * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html | ||
247 | * for a detailed explanation of the infix-to-postfix algorithm on which | ||
248 | * this is based (this code differs in that it applies operators immediately | ||
249 | * to the stack instead of adding them to a queue to end up with an | ||
250 | * expression). */ | ||
251 | |||
252 | #define arith_isspace(arithval) \ | ||
253 | (arithval == ' ' || arithval == '\v' || arithval == '\t' || arithval == '\f') | ||
254 | |||
255 | |||
256 | typedef unsigned char operator; | ||
257 | |||
258 | /* An operator's token id is a bit of a bitfield. The lower 5 bits are the | ||
259 | * precedence, and 3 high bits are an ID unique across operators of that | ||
260 | * precedence. The ID portion is so that multiple operators can have the | ||
261 | * same precedence, ensuring that the leftmost one is evaluated first. | ||
262 | * Consider * and /. */ | ||
263 | |||
264 | #define tok_decl(prec,id) (((id)<<5)|(prec)) | ||
265 | #define PREC(op) ((op) & 0x1F) | ||
266 | |||
267 | #define TOK_LPAREN tok_decl(0,0) | ||
268 | |||
269 | #define TOK_COMMA tok_decl(1,0) | ||
270 | |||
271 | /* conditional is right associativity too */ | ||
272 | #define TOK_CONDITIONAL tok_decl(2,0) | ||
273 | #define TOK_CONDITIONAL_SEP tok_decl(2,1) | ||
274 | |||
275 | #define TOK_OR tok_decl(3,0) | ||
276 | |||
277 | #define TOK_AND tok_decl(4,0) | ||
278 | |||
279 | #define TOK_BOR tok_decl(5,0) | ||
280 | |||
281 | #define TOK_BXOR tok_decl(6,0) | ||
282 | |||
283 | #define TOK_BAND tok_decl(7,0) | ||
284 | |||
285 | #define TOK_EQ tok_decl(8,0) | ||
286 | #define TOK_NE tok_decl(8,1) | ||
287 | |||
288 | #define TOK_LT tok_decl(9,0) | ||
289 | #define TOK_GT tok_decl(9,1) | ||
290 | #define TOK_GE tok_decl(9,2) | ||
291 | #define TOK_LE tok_decl(9,3) | ||
292 | |||
293 | #define TOK_LSHIFT tok_decl(10,0) | ||
294 | #define TOK_RSHIFT tok_decl(10,1) | ||
295 | |||
296 | #define TOK_ADD tok_decl(11,0) | ||
297 | #define TOK_SUB tok_decl(11,1) | ||
298 | |||
299 | #define TOK_MUL tok_decl(12,0) | ||
300 | #define TOK_DIV tok_decl(12,1) | ||
301 | #define TOK_REM tok_decl(12,2) | ||
302 | |||
303 | /* For now unary operators. */ | ||
304 | #define UNARYPREC 13 | ||
305 | #define TOK_BNOT tok_decl(UNARYPREC,0) | ||
306 | #define TOK_NOT tok_decl(UNARYPREC,1) | ||
307 | |||
308 | #define TOK_UMINUS tok_decl(UNARYPREC+1,0) | ||
309 | #define TOK_UPLUS tok_decl(UNARYPREC+1,1) | ||
310 | |||
311 | #define SPEC_PREC (UNARYPREC+1) | ||
312 | |||
313 | #define TOK_NUM tok_decl(SPEC_PREC, 0) | ||
314 | #define TOK_RPAREN tok_decl(SPEC_PREC, 1) | ||
192 | 315 | ||
193 | /* stupid C lexical analyser */ | 316 | #define NUMPTR (*numstackptr) |
194 | static void c_lex(const char *fname, long fsize) | 317 | |
318 | typedef struct ARITCH_VAR_NUM { | ||
319 | arith_t val; | ||
320 | arith_t contidional_second_val; | ||
321 | char contidional_second_val_initialized; | ||
322 | } v_n_t; | ||
323 | |||
324 | |||
325 | typedef struct CHK_VAR_RECURSIVE_LOOPED { | ||
326 | const char *var; | ||
327 | size_t var_sz; | ||
328 | struct CHK_VAR_RECURSIVE_LOOPED *next; | ||
329 | } chk_var_recursive_looped_t; | ||
330 | |||
331 | static chk_var_recursive_looped_t *prev_chk_var_recursive; | ||
332 | |||
333 | |||
334 | static int arith_lookup_val(const char *var, size_t key_sz, arith_t *pval) | ||
335 | { | ||
336 | const char * p = lookup_key(var, key_sz); | ||
337 | |||
338 | if(p) { | ||
339 | int errcode; | ||
340 | |||
341 | /* recursive try as expression */ | ||
342 | chk_var_recursive_looped_t *cur; | ||
343 | chk_var_recursive_looped_t cur_save; | ||
344 | |||
345 | for(cur = prev_chk_var_recursive; cur; cur = cur->next) { | ||
346 | if(cur->var_sz == key_sz && memcmp(cur->var, var, key_sz) == 0) { | ||
347 | /* expression recursion loop detected */ | ||
348 | return -5; | ||
349 | } | ||
350 | } | ||
351 | /* save current lookuped var name */ | ||
352 | cur = prev_chk_var_recursive; | ||
353 | cur_save.var = var; | ||
354 | cur_save.var_sz = key_sz; | ||
355 | cur_save.next = cur; | ||
356 | prev_chk_var_recursive = &cur_save; | ||
357 | |||
358 | *pval = arith (p, &errcode); | ||
359 | /* restore previous ptr after recursiving */ | ||
360 | prev_chk_var_recursive = cur; | ||
361 | return errcode; | ||
362 | } else { | ||
363 | /* disallow undefined var */ | ||
364 | fprintf(stderr, "%.*s ", (int)key_sz, var); | ||
365 | return -4; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | /* "applying" a token means performing it on the top elements on the integer | ||
370 | * stack. For a unary operator it will only change the top element, but a | ||
371 | * binary operator will pop two arguments and push a result */ | ||
372 | static inline int | ||
373 | arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr) | ||
374 | { | ||
375 | v_n_t *numptr_m1; | ||
376 | arith_t numptr_val, rez; | ||
377 | |||
378 | if (NUMPTR == numstack) goto err; /* There is no operator that can work | ||
379 | without arguments */ | ||
380 | numptr_m1 = NUMPTR - 1; | ||
381 | |||
382 | rez = numptr_m1->val; | ||
383 | if (op == TOK_UMINUS) | ||
384 | rez *= -1; | ||
385 | else if (op == TOK_NOT) | ||
386 | rez = !rez; | ||
387 | else if (op == TOK_BNOT) | ||
388 | rez = ~rez; | ||
389 | else if (op != TOK_UPLUS) { | ||
390 | /* Binary operators */ | ||
391 | |||
392 | /* check and binary operators need two arguments */ | ||
393 | if (numptr_m1 == numstack) goto err; | ||
394 | |||
395 | /* ... and they pop one */ | ||
396 | --NUMPTR; | ||
397 | numptr_val = rez; | ||
398 | if (op == TOK_CONDITIONAL) { | ||
399 | if(! numptr_m1->contidional_second_val_initialized) { | ||
400 | /* protect $((expr1 ? expr2)) without ": expr" */ | ||
401 | goto err; | ||
402 | } | ||
403 | rez = numptr_m1->contidional_second_val; | ||
404 | } else if(numptr_m1->contidional_second_val_initialized) { | ||
405 | /* protect $((expr1 : expr2)) without "expr ? " */ | ||
406 | goto err; | ||
407 | } | ||
408 | numptr_m1 = NUMPTR - 1; | ||
409 | if (op == TOK_CONDITIONAL) { | ||
410 | numptr_m1->contidional_second_val = rez; | ||
411 | } | ||
412 | rez = numptr_m1->val; | ||
413 | if (op == TOK_BOR) | ||
414 | rez |= numptr_val; | ||
415 | else if (op == TOK_OR) | ||
416 | rez = numptr_val || rez; | ||
417 | else if (op == TOK_BAND) | ||
418 | rez &= numptr_val; | ||
419 | else if (op == TOK_BXOR) | ||
420 | rez ^= numptr_val; | ||
421 | else if (op == TOK_AND) | ||
422 | rez = rez && numptr_val; | ||
423 | else if (op == TOK_EQ) | ||
424 | rez = (rez == numptr_val); | ||
425 | else if (op == TOK_NE) | ||
426 | rez = (rez != numptr_val); | ||
427 | else if (op == TOK_GE) | ||
428 | rez = (rez >= numptr_val); | ||
429 | else if (op == TOK_RSHIFT) | ||
430 | rez >>= numptr_val; | ||
431 | else if (op == TOK_LSHIFT) | ||
432 | rez <<= numptr_val; | ||
433 | else if (op == TOK_GT) | ||
434 | rez = (rez > numptr_val); | ||
435 | else if (op == TOK_LT) | ||
436 | rez = (rez < numptr_val); | ||
437 | else if (op == TOK_LE) | ||
438 | rez = (rez <= numptr_val); | ||
439 | else if (op == TOK_MUL) | ||
440 | rez *= numptr_val; | ||
441 | else if (op == TOK_ADD) | ||
442 | rez += numptr_val; | ||
443 | else if (op == TOK_SUB) | ||
444 | rez -= numptr_val; | ||
445 | else if (op == TOK_COMMA) | ||
446 | rez = numptr_val; | ||
447 | else if (op == TOK_CONDITIONAL_SEP) { | ||
448 | if (numptr_m1 == numstack) { | ||
449 | /* protect $((expr : expr)) without "expr ? " */ | ||
450 | goto err; | ||
451 | } | ||
452 | numptr_m1->contidional_second_val_initialized = op; | ||
453 | numptr_m1->contidional_second_val = numptr_val; | ||
454 | } | ||
455 | else if (op == TOK_CONDITIONAL) { | ||
456 | rez = rez ? | ||
457 | numptr_val : numptr_m1->contidional_second_val; | ||
458 | } | ||
459 | else if(numptr_val==0) /* zero divisor check */ | ||
460 | return -2; | ||
461 | else if (op == TOK_DIV) | ||
462 | rez /= numptr_val; | ||
463 | else if (op == TOK_REM) | ||
464 | rez %= numptr_val; | ||
465 | } | ||
466 | numptr_m1->val = rez; | ||
467 | return 0; | ||
468 | err: return(-1); | ||
469 | } | ||
470 | |||
471 | /* longest must first */ | ||
472 | static const char op_tokens[] = { | ||
473 | '<','<', 0, TOK_LSHIFT, | ||
474 | '>','>', 0, TOK_RSHIFT, | ||
475 | '|','|', 0, TOK_OR, | ||
476 | '&','&', 0, TOK_AND, | ||
477 | '!','=', 0, TOK_NE, | ||
478 | '<','=', 0, TOK_LE, | ||
479 | '>','=', 0, TOK_GE, | ||
480 | '=','=', 0, TOK_EQ, | ||
481 | '!', 0, TOK_NOT, | ||
482 | '<', 0, TOK_LT, | ||
483 | '>', 0, TOK_GT, | ||
484 | '|', 0, TOK_BOR, | ||
485 | '&', 0, TOK_BAND, | ||
486 | '*', 0, TOK_MUL, | ||
487 | '/', 0, TOK_DIV, | ||
488 | '%', 0, TOK_REM, | ||
489 | '+', 0, TOK_ADD, | ||
490 | '-', 0, TOK_SUB, | ||
491 | '^', 0, TOK_BXOR, | ||
492 | '~', 0, TOK_BNOT, | ||
493 | ',', 0, TOK_COMMA, | ||
494 | '?', 0, TOK_CONDITIONAL, | ||
495 | ':', 0, TOK_CONDITIONAL_SEP, | ||
496 | ')', 0, TOK_RPAREN, | ||
497 | '(', 0, TOK_LPAREN, | ||
498 | 0 | ||
499 | }; | ||
500 | /* ptr to ")" */ | ||
501 | #define endexpression &op_tokens[sizeof(op_tokens)-7] | ||
502 | |||
503 | /* | ||
504 | * Return of a legal variable name (a letter or underscore followed by zero or | ||
505 | * more letters, underscores, and digits). | ||
506 | */ | ||
507 | |||
508 | static inline char * | ||
509 | endofname(const char *name) | ||
510 | { | ||
511 | char *p; | ||
512 | |||
513 | p = (char *) name; | ||
514 | if (! ID(*p)) | ||
515 | return p; | ||
516 | while (*++p) { | ||
517 | if (! ISALNUM(*p)) | ||
518 | break; | ||
519 | } | ||
520 | return p; | ||
521 | } | ||
522 | |||
523 | |||
524 | /* Like strncpy but make sure the resulting string is always 0 terminated. */ | ||
525 | static inline char * safe_strncpy(char *dst, const char *src, size_t size) | ||
526 | { | ||
527 | dst[size-1] = '\0'; | ||
528 | return strncpy(dst, src, size-1); | ||
529 | } | ||
530 | |||
531 | static arith_t arith (const char *expr, int *perrcode) | ||
532 | { | ||
533 | char arithval; /* Current character under analysis */ | ||
534 | operator lasttok, op; | ||
535 | operator prec; | ||
536 | |||
537 | const char *p = endexpression; | ||
538 | int errcode; | ||
539 | |||
540 | size_t datasizes = strlen(expr) + 2; | ||
541 | |||
542 | /* Stack of integers */ | ||
543 | /* The proof that there can be no more than strlen(startbuf)/2+1 integers | ||
544 | * in any given correct or incorrect expression is left as an exercise to | ||
545 | * the reader. */ | ||
546 | v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)), | ||
547 | *numstackptr = numstack; | ||
548 | /* Stack of operator tokens */ | ||
549 | operator *stack = alloca((datasizes) * sizeof(operator)), | ||
550 | *stackptr = stack; | ||
551 | |||
552 | *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */ | ||
553 | *perrcode = errcode = 0; | ||
554 | |||
555 | while(1) { | ||
556 | if ((arithval = *expr) == 0) { | ||
557 | if (p == endexpression) { | ||
558 | /* Null expression. */ | ||
559 | err: | ||
560 | return (*perrcode = -1); | ||
561 | } | ||
562 | |||
563 | /* This is only reached after all tokens have been extracted from the | ||
564 | * input stream. If there are still tokens on the operator stack, they | ||
565 | * are to be applied in order. At the end, there should be a final | ||
566 | * result on the integer stack */ | ||
567 | |||
568 | if (expr != endexpression + 1) { | ||
569 | /* If we haven't done so already, */ | ||
570 | /* append a closing right paren */ | ||
571 | expr = endexpression; | ||
572 | /* and let the loop process it. */ | ||
573 | continue; | ||
574 | } | ||
575 | /* At this point, we're done with the expression. */ | ||
576 | if (numstackptr != numstack+1) { | ||
577 | /* ... but if there isn't, it's bad */ | ||
578 | goto err; | ||
579 | } | ||
580 | ret: | ||
581 | *perrcode = errcode; | ||
582 | return numstack->val; | ||
583 | } else { | ||
584 | /* Continue processing the expression. */ | ||
585 | if (arith_isspace(arithval)) { | ||
586 | /* Skip whitespace */ | ||
587 | goto prologue; | ||
588 | } | ||
589 | if((p = endofname(expr)) != expr) { | ||
590 | size_t var_name_size = (p-expr); | ||
591 | |||
592 | if(var_name_size == 7 && | ||
593 | strncmp(expr, "defined", var_name_size) == 0) { | ||
594 | int brace_form = 0; | ||
595 | const char *v; | ||
596 | |||
597 | while(arith_isspace(*p)) p++; | ||
598 | if(*p == '(') { | ||
599 | p++; | ||
600 | while(arith_isspace(*p)) p++; | ||
601 | brace_form = 1; | ||
602 | } | ||
603 | expr = p; | ||
604 | if((p = endofname(expr)) == expr) | ||
605 | goto err; | ||
606 | var_name_size = (p-expr); | ||
607 | while(arith_isspace(*p)) p++; | ||
608 | if(brace_form && *p++ != ')') | ||
609 | goto err; | ||
610 | v = lookup_key(expr, var_name_size); | ||
611 | numstackptr->val = (v != NULL) ? 1 : 0; | ||
612 | } else { | ||
613 | errcode = arith_lookup_val(expr, var_name_size, | ||
614 | &(numstackptr->val)); | ||
615 | if(errcode) goto ret; | ||
616 | } | ||
617 | expr = p; | ||
618 | num: | ||
619 | numstackptr->contidional_second_val_initialized = 0; | ||
620 | numstackptr++; | ||
621 | lasttok = TOK_NUM; | ||
622 | continue; | ||
623 | } else if (arithval >= '0' && arithval <= '9') { | ||
624 | numstackptr->val = strtoll(expr, (char **) &expr, 0); | ||
625 | while(*expr == 'l' || *expr == 'L' || *expr == 'u' || | ||
626 | *expr == 'U') | ||
627 | expr++; | ||
628 | goto num; | ||
629 | } | ||
630 | for(p = op_tokens; ; p++) { | ||
631 | const char *o; | ||
632 | |||
633 | if(*p == 0) { | ||
634 | /* strange operator not found */ | ||
635 | goto err; | ||
636 | } | ||
637 | for(o = expr; *p && *o == *p; p++) | ||
638 | o++; | ||
639 | if(! *p) { | ||
640 | /* found */ | ||
641 | expr = o - 1; | ||
642 | break; | ||
643 | } | ||
644 | /* skip tail uncompared token */ | ||
645 | while(*p) | ||
646 | p++; | ||
647 | /* skip zero delim */ | ||
648 | p++; | ||
649 | } | ||
650 | op = p[1]; | ||
651 | |||
652 | /* Plus and minus are binary (not unary) _only_ if the last | ||
653 | * token was as number, or a right paren (which pretends to be | ||
654 | * a number, since it evaluates to one). Think about it. | ||
655 | * It makes sense. */ | ||
656 | if (lasttok != TOK_NUM) { | ||
657 | if(op == TOK_ADD) | ||
658 | op = TOK_UPLUS; | ||
659 | else if(op == TOK_SUB) | ||
660 | op = TOK_UMINUS; | ||
661 | } | ||
662 | /* We don't want a unary operator to cause recursive descent on the | ||
663 | * stack, because there can be many in a row and it could cause an | ||
664 | * operator to be evaluated before its argument is pushed onto the | ||
665 | * integer stack. */ | ||
666 | /* But for binary operators, "apply" everything on the operator | ||
667 | * stack until we find an operator with a lesser priority than the | ||
668 | * one we have just extracted. */ | ||
669 | /* Left paren is given the lowest priority so it will never be | ||
670 | * "applied" in this way. | ||
671 | * if associativity is right and priority eq, applied also skip | ||
672 | */ | ||
673 | prec = PREC(op); | ||
674 | if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { | ||
675 | /* not left paren or unary */ | ||
676 | if (lasttok != TOK_NUM) { | ||
677 | /* binary op must be preceded by a num */ | ||
678 | goto err; | ||
679 | } | ||
680 | while (stackptr != stack) { | ||
681 | if (op == TOK_RPAREN) { | ||
682 | /* The algorithm employed here is simple: while we don't | ||
683 | * hit an open paren nor the bottom of the stack, pop | ||
684 | * tokens and apply them */ | ||
685 | if (stackptr[-1] == TOK_LPAREN) { | ||
686 | --stackptr; | ||
687 | /* Any operator directly after a */ | ||
688 | lasttok = TOK_NUM; | ||
689 | /* close paren should consider itself binary */ | ||
690 | goto prologue; | ||
691 | } | ||
692 | } else { | ||
693 | operator prev_prec = PREC(stackptr[-1]); | ||
694 | |||
695 | if (prev_prec < prec) | ||
696 | break; | ||
697 | /* check right assoc */ | ||
698 | if(prev_prec == prec && prec == PREC(TOK_CONDITIONAL)) | ||
699 | break; | ||
700 | } | ||
701 | errcode = arith_apply(*--stackptr, numstack, &numstackptr); | ||
702 | if(errcode) goto ret; | ||
703 | } | ||
704 | if (op == TOK_RPAREN) { | ||
705 | goto err; | ||
706 | } | ||
707 | } | ||
708 | |||
709 | /* Push this operator to the stack and remember it. */ | ||
710 | *stackptr++ = lasttok = op; | ||
711 | |||
712 | prologue: | ||
713 | ++expr; | ||
714 | } | ||
715 | } | ||
716 | } | ||
717 | |||
718 | /* stupid C lexical analyser for configs.h */ | ||
719 | static void c_lex_config(const char *fname, long fsize) | ||
195 | { | 720 | { |
196 | int c; | 721 | int c; |
197 | int state; | 722 | int state; |
198 | int line; | 723 | int line; |
199 | char *id = id_s; | 724 | char *id = id_s; |
200 | size_t id_len = 0; /* stupid initialization */ | 725 | size_t id_len = 0; /* stupid initialize */ |
201 | unsigned char *optr, *oend; | 726 | unsigned char *optr, *oend; |
727 | int mode = CONFIG_MODE; | ||
202 | 728 | ||
203 | int fd; | 729 | int fd; |
204 | char *map; | 730 | char *map; |
@@ -242,6 +768,8 @@ static void c_lex(const char *fname, long fsize) | |||
242 | /* <S><<EOF>> */ | 768 | /* <S><<EOF>> */ |
243 | munmap(map, mapsize); | 769 | munmap(map, mapsize); |
244 | close(fd); | 770 | close(fd); |
771 | if(mode != CONFIG_MODE) | ||
772 | yy_error_d("expected #endif"); | ||
245 | return; | 773 | return; |
246 | } | 774 | } |
247 | if(c == REM) { | 775 | if(c == REM) { |
@@ -282,7 +810,7 @@ static void c_lex(const char *fname, long fsize) | |||
282 | 810 | ||
283 | /* trick for fast drop id | 811 | /* trick for fast drop id |
284 | if key with this first char undefined */ | 812 | if key with this first char undefined */ |
285 | if(first_chars[c] == 0) { | 813 | if(first_chars[c] == 0 || (mode & FALSE_MODES) != 0) { |
286 | /* skip <S>[A-Z_a-z0-9]+ */ | 814 | /* skip <S>[A-Z_a-z0-9]+ */ |
287 | do getc1(); while(isalnums[c]); | 815 | do getc1(); while(isalnums[c]); |
288 | } else { | 816 | } else { |
@@ -314,30 +842,37 @@ static void c_lex(const char *fname, long fsize) | |||
314 | } | 842 | } |
315 | if(state == POUND) { | 843 | if(state == POUND) { |
316 | /* tricks */ | 844 | /* tricks */ |
317 | static const char * const preproc[] = { | 845 | int diu = (int)first_chars_deiu[c]; /* preproc ptr */ |
318 | /* 0 1 2 3 4 5 6 */ | ||
319 | "", "", "", "", "ndef", "efine", "nclude" | ||
320 | }; | ||
321 | size_t diu = first_chars_diu[c]; /* strlen and preproc ptr */ | ||
322 | 846 | ||
323 | state = S; | 847 | state = S; |
324 | if(diu != S) { | 848 | if(diu != S) { |
849 | int p_num_str, p_num_max; | ||
850 | |||
325 | getc1(); | 851 | getc1(); |
326 | id_len = 0; | 852 | id_len = 0; |
327 | while(isalnums[c]) { | 853 | while(isalnums[c]) { |
328 | put_id(c); | 854 | put_id(c); |
329 | getc1(); | 855 | getc1(); |
330 | } | 856 | } |
331 | /* str begins with c, read == strlen key and compared */ | 857 | put_id(0); |
332 | if(diu == id_len && !memcmp(id, preproc[diu], diu)) { | 858 | p_num_str = diu & 0xf; |
333 | state = diu + '0'; | 859 | p_num_max = diu >> 4; |
334 | id_len = 0; /* common for save */ | 860 | for(diu = p_num_str; diu <= p_num_max; diu++) |
861 | if(!strcmp(id, preproc[diu])) { | ||
862 | state = (diu + '0'); | ||
863 | /* common */ | ||
864 | id_len = 0; | ||
865 | break; | ||
335 | } | 866 | } |
336 | } else { | 867 | } else { |
337 | while(isalnums[c]) getc1(); | 868 | while(isalnums[c]) getc1(); |
338 | } | 869 | } |
870 | } else if(state == EF) { | ||
871 | /* #endif */ | ||
872 | pop_mode(); | ||
873 | state = S; | ||
339 | } else if(state == I) { | 874 | } else if(state == I) { |
340 | if(c == STR) { | 875 | if(c == STR && (mode & FALSE_MODES) == 0) { |
341 | /* <I>\" */ | 876 | /* <I>\" */ |
342 | for(;;) { | 877 | for(;;) { |
343 | getc1(); | 878 | getc1(); |
@@ -354,31 +889,84 @@ static void c_lex(const char *fname, long fsize) | |||
354 | } | 889 | } |
355 | /* else another (may be wrong) #include ... */ | 890 | /* else another (may be wrong) #include ... */ |
356 | state = S; | 891 | state = S; |
892 | } else if(state == F) { | ||
893 | arith_t t; | ||
894 | int errcode; | ||
895 | |||
896 | while(c != '\n' && c != L_EOF) { | ||
897 | put_id(c); | ||
898 | getc1(); | ||
899 | } | ||
900 | put_id(0); | ||
901 | t = arith(id, &errcode); | ||
902 | if (errcode < 0) { | ||
903 | if (errcode == -2) | ||
904 | yy_error_d("divide by zero"); | ||
905 | else if (errcode == -4) | ||
906 | yy_error_d("undefined"); | ||
907 | else if (errcode == -5) | ||
908 | yy_error_d("expression recursion loop detected"); | ||
909 | else | ||
910 | yy_error_d("syntax error"); | ||
911 | } | ||
912 | push_mode(); | ||
913 | mode = t != 0 ? IF1_MODE : IF0_MODE; | ||
914 | state = S; | ||
915 | } else if(state == IFD || state == IFND) { | ||
916 | /* save KEY from #if(n)def KEY ... */ | ||
917 | const char *v; | ||
918 | |||
919 | push_mode(); | ||
920 | while(isalnums[c]) { | ||
921 | put_id(c); | ||
922 | getc1(); | ||
923 | } | ||
924 | if(!id_len) | ||
925 | yy_error_d("expected identifier"); | ||
926 | v = lookup_key(id, id_len); | ||
927 | mode = IF1_MODE; | ||
928 | if(state == IFD && v == NULL) | ||
929 | mode = IF0_MODE; | ||
930 | else if(state == IFND && v != NULL) | ||
931 | mode = IF0_MODE; | ||
932 | state = S; | ||
933 | } else if(state == EI) { | ||
934 | /* #elif */ | ||
935 | if(mode == CONFIG_MODE || mode == ELSE0_MODE || mode == ELSE1_MODE) | ||
936 | yy_error_d("unexpected #elif"); | ||
937 | if(mode == IF0_MODE) { | ||
938 | pop_mode(); | ||
939 | state = F; | ||
940 | } else { | ||
941 | mode = ELIF1_MODE; | ||
942 | state = S; | ||
943 | } | ||
944 | } else if(state == E) { | ||
945 | if(mode == CONFIG_MODE || mode == ELSE0_MODE || mode == ELSE1_MODE) | ||
946 | yy_error_d("unexpected #else"); | ||
947 | if(mode == IF0_MODE) | ||
948 | mode = ELSE0_MODE; | ||
949 | else if(mode == IF1_MODE) | ||
950 | mode = ELSE1_MODE; | ||
951 | state = S; | ||
357 | } else if(state == D || state == U) { | 952 | } else if(state == D || state == U) { |
358 | if(mode == SOURCES_MODE) { | 953 | /* save KEY from #"define"|"undef" ... */ |
359 | /* ignore depend with #define or #undef KEY */ | 954 | while(isalnums[c]) { |
360 | while(isalnums[c]) getc1(); | 955 | put_id(c); |
956 | getc1(); | ||
957 | } | ||
958 | if(!id_len) | ||
959 | yy_error_d("expected identifier"); | ||
960 | if(state == U) { | ||
961 | if((mode & FALSE_MODES) == 0) | ||
962 | parse_conf_opt(id, NULL, id_len); | ||
361 | state = S; | 963 | state = S; |
362 | } else { | 964 | } else { |
363 | /* save KEY from #"define"|"undef" ... */ | 965 | /* D -> DK */ |
364 | while(isalnums[c]) { | 966 | state = DK; |
365 | put_id(c); | ||
366 | getc1(); | ||
367 | } | ||
368 | if(!id_len) | ||
369 | yy_error_d("expected identifier"); | ||
370 | if(state == U) { | ||
371 | parse_conf_opt(id, NULL, id_len); | ||
372 | state = S; | ||
373 | } else { | ||
374 | /* D -> DK */ | ||
375 | if(c == '(') | ||
376 | yy_error_d("unexpected function macro"); | ||
377 | state = DK; | ||
378 | } | ||
379 | } | 967 | } |
380 | } else { | 968 | } else { |
381 | /* state==<DK> #define KEY[ ] (config mode) */ | 969 | /* state==<DK> #define KEY[ ] */ |
382 | size_t opt_len = id_len; | 970 | size_t opt_len = id_len; |
383 | char *val = id + opt_len; | 971 | char *val = id + opt_len; |
384 | char *sp; | 972 | char *sp; |
@@ -395,7 +983,8 @@ static void c_lex(const char *fname, long fsize) | |||
395 | while(--sp >= val && (*sp == ' ' || *sp == '\t' | 983 | while(--sp >= val && (*sp == ' ' || *sp == '\t' |
396 | || *sp == '\f' || *sp == '\v')) | 984 | || *sp == '\f' || *sp == '\v')) |
397 | *sp = '\0'; | 985 | *sp = '\0'; |
398 | parse_conf_opt(id, val, opt_len); | 986 | if((mode & FALSE_MODES) == 0) |
987 | parse_conf_opt(id, val, opt_len); | ||
399 | state = S; | 988 | state = S; |
400 | } | 989 | } |
401 | } | 990 | } |
@@ -426,8 +1015,219 @@ too_long: | |||
426 | yy_error_d("phrase too long"); | 1015 | yy_error_d("phrase too long"); |
427 | } | 1016 | } |
428 | 1017 | ||
1018 | /* trick for fast find "define", "include", "undef" */ | ||
1019 | static const char first_chars_diu[UCHAR_MAX] = { | ||
1020 | [(int)'d'] = (char)5, /* strlen("define") - 1; */ | ||
1021 | [(int)'i'] = (char)6, /* strlen("include") - 1; */ | ||
1022 | [(int)'u'] = (char)4, /* strlen("undef") - 1; */ | ||
1023 | }; | ||
1024 | |||
1025 | #undef D | ||
1026 | #undef I | ||
1027 | #undef U | ||
1028 | #define D '5' /* #define preprocessor's directive */ | ||
1029 | #define I '6' /* #include preprocessor's directive */ | ||
1030 | #define U '4' /* #undef preprocessor's directive */ | ||
1031 | |||
1032 | /* stupid C lexical analyser for sources */ | ||
1033 | static void c_lex_src(const char *fname, long fsize) | ||
1034 | { | ||
1035 | int c; | ||
1036 | int state; | ||
1037 | int line; | ||
1038 | char *id = id_s; | ||
1039 | size_t id_len = 0; /* stupid initialize */ | ||
1040 | unsigned char *optr, *oend; | ||
1041 | |||
1042 | int fd; | ||
1043 | char *map; | ||
1044 | int mapsize; | ||
429 | 1045 | ||
430 | /* bb_simplify_path special variant for absolute pathname */ | 1046 | if(fsize == 0) { |
1047 | fprintf(stderr, "Warning: %s is empty\n", fname); | ||
1048 | return; | ||
1049 | } | ||
1050 | fd = open(fname, O_RDONLY); | ||
1051 | if(fd < 0) { | ||
1052 | perror(fname); | ||
1053 | return; | ||
1054 | } | ||
1055 | mapsize = (fsize+pagesizem1) & ~pagesizem1; | ||
1056 | map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0); | ||
1057 | if ((long) map == -1) | ||
1058 | bb_error_d("%s: mmap: %m", fname); | ||
1059 | |||
1060 | optr = (unsigned char *)map; | ||
1061 | oend = optr + fsize; | ||
1062 | |||
1063 | line = 1; | ||
1064 | state = S; | ||
1065 | |||
1066 | for(;;) { | ||
1067 | getc1(); | ||
1068 | for(;;) { | ||
1069 | /* [ \t]+ eat first space */ | ||
1070 | while(c == ' ' || c == '\t') | ||
1071 | getc1(); | ||
1072 | |||
1073 | if(state == S) { | ||
1074 | while(first_chars[c] == ANY) { | ||
1075 | /* <S>unparsed */ | ||
1076 | if(c == '\n') | ||
1077 | line++; | ||
1078 | getc1(); | ||
1079 | } | ||
1080 | if(c == L_EOF) { | ||
1081 | /* <S><<EOF>> */ | ||
1082 | munmap(map, mapsize); | ||
1083 | close(fd); | ||
1084 | return; | ||
1085 | } | ||
1086 | if(c == REM) { | ||
1087 | /* <S>/ */ | ||
1088 | getc0(); | ||
1089 | if(c == REM) { | ||
1090 | /* <S>"//"[^\n]* */ | ||
1091 | do getc0(); while(c != '\n' && c != L_EOF); | ||
1092 | } else if(c == '*') { | ||
1093 | /* <S>[/][*] goto parse block comments */ | ||
1094 | break; | ||
1095 | } | ||
1096 | } else if(c == POUND) { | ||
1097 | /* <S># */ | ||
1098 | state = c; | ||
1099 | getc1(); | ||
1100 | } else if(c == STR || c == CHR) { | ||
1101 | /* <S>\"|\' */ | ||
1102 | int qc = c; | ||
1103 | |||
1104 | for(;;) { | ||
1105 | /* <STR,CHR>. */ | ||
1106 | getc1(); | ||
1107 | if(c == qc) { | ||
1108 | /* <STR>\" or <CHR>\' */ | ||
1109 | break; | ||
1110 | } | ||
1111 | if(c == BS) { | ||
1112 | /* <STR,CHR>\\ but is not <STR,CHR>\\\n */ | ||
1113 | getc0(); | ||
1114 | } | ||
1115 | if(c == '\n' || c == L_EOF) | ||
1116 | yy_error_d("unterminated"); | ||
1117 | } | ||
1118 | getc1(); | ||
1119 | } else { | ||
1120 | /* <S>[A-Z_a-z0-9] */ | ||
1121 | |||
1122 | /* trick for fast drop id | ||
1123 | if key with this first char undefined */ | ||
1124 | if(first_chars[c] == 0) { | ||
1125 | /* skip <S>[A-Z_a-z0-9]+ */ | ||
1126 | do getc1(); while(isalnums[c]); | ||
1127 | } else { | ||
1128 | id_len = 0; | ||
1129 | do { | ||
1130 | /* <S>[A-Z_a-z0-9]+ */ | ||
1131 | put_id(c); | ||
1132 | getc1(); | ||
1133 | } while(isalnums[c]); | ||
1134 | check_key(key_top, id, id_len); | ||
1135 | } | ||
1136 | } | ||
1137 | continue; | ||
1138 | } | ||
1139 | /* begin preprocessor states */ | ||
1140 | if(c == L_EOF) | ||
1141 | yy_error_d("unexpected EOF"); | ||
1142 | if(c == REM) { | ||
1143 | /* <#.*>/ */ | ||
1144 | getc0(); | ||
1145 | if(c == REM) | ||
1146 | yy_error_d("detected // in preprocessor line"); | ||
1147 | if(c == '*') { | ||
1148 | /* <#.*>[/][*] goto parse block comments */ | ||
1149 | break; | ||
1150 | } | ||
1151 | /* hmm, #.*[/] */ | ||
1152 | yy_error_d("strange preprocessor line"); | ||
1153 | } | ||
1154 | if(state == POUND) { | ||
1155 | /* tricks */ | ||
1156 | static const char * const p_preproc[] = { | ||
1157 | /* 0 1 2 3 4 5 6 */ | ||
1158 | "", "", "", "", "ndef", "efine", "nclude" | ||
1159 | }; | ||
1160 | size_t diu = first_chars_diu[c]; /* strlen and p_preproc ptr */ | ||
1161 | |||
1162 | state = S; | ||
1163 | if(diu != S) { | ||
1164 | getc1(); | ||
1165 | id_len = 0; | ||
1166 | while(isalnums[c]) { | ||
1167 | put_id(c); | ||
1168 | getc1(); | ||
1169 | } | ||
1170 | /* have str begined with c, readed == strlen key and compared */ | ||
1171 | if(diu == id_len && !memcmp(id, p_preproc[diu], diu)) { | ||
1172 | state = diu + '0'; | ||
1173 | id_len = 0; /* common for save */ | ||
1174 | } | ||
1175 | } else { | ||
1176 | while(isalnums[c]) getc1(); | ||
1177 | } | ||
1178 | } else if(state == I) { | ||
1179 | if(c == STR) { | ||
1180 | /* <I>\" */ | ||
1181 | for(;;) { | ||
1182 | getc1(); | ||
1183 | if(c == STR) | ||
1184 | break; | ||
1185 | if(c == L_EOF) | ||
1186 | yy_error_d("unexpected EOF"); | ||
1187 | put_id(c); | ||
1188 | } | ||
1189 | put_id(0); | ||
1190 | /* store "include.h" */ | ||
1191 | parse_inc(id, fname); | ||
1192 | getc1(); | ||
1193 | } | ||
1194 | /* else another (may be wrong) #include ... */ | ||
1195 | state = S; | ||
1196 | } else /* if(state == D || state == U) */ { | ||
1197 | /* ignore depend with #define or #undef KEY */ | ||
1198 | while(isalnums[c]) getc1(); | ||
1199 | state = S; | ||
1200 | } | ||
1201 | } | ||
1202 | |||
1203 | /* <REM> */ | ||
1204 | getc0(); | ||
1205 | for(;;) { | ||
1206 | /* <REM>[^*]+ */ | ||
1207 | while(c != '*') { | ||
1208 | if(c == '\n') { | ||
1209 | /* <REM>\n */ | ||
1210 | if(state != S) | ||
1211 | yy_error_d("unexpected newline"); | ||
1212 | line++; | ||
1213 | } else if(c == L_EOF) | ||
1214 | yy_error_d("unexpected EOF"); | ||
1215 | getc0(); | ||
1216 | } | ||
1217 | /* <REM>[*] */ | ||
1218 | getc0(); | ||
1219 | if(c == REM) { | ||
1220 | /* <REM>[*][/] */ | ||
1221 | break; | ||
1222 | } | ||
1223 | } | ||
1224 | } | ||
1225 | too_long: | ||
1226 | yy_error_d("phrase too long"); | ||
1227 | } | ||
1228 | |||
1229 | |||
1230 | /* bb_simplify_path special variant for apsolute pathname */ | ||
431 | static size_t bb_qa_simplify_path(char *path) | 1231 | static size_t bb_qa_simplify_path(char *path) |
432 | { | 1232 | { |
433 | char *s, *p; | 1233 | char *s, *p; |
@@ -477,7 +1277,7 @@ static void parse_inc(const char *include, const char *fname) | |||
477 | const char *p; | 1277 | const char *p; |
478 | 1278 | ||
479 | lo = Iop; | 1279 | lo = Iop; |
480 | p = strrchr(fname, '/'); /* fname has absolute pathname */ | 1280 | p = strrchr(fname, '/'); /* fname have absolute pathname */ |
481 | w = (p-fname); | 1281 | w = (p-fname); |
482 | /* find from current directory of source file */ | 1282 | /* find from current directory of source file */ |
483 | ap = bb_asprint("%.*s/%s", w, fname, include); | 1283 | ap = bb_asprint("%.*s/%s", w, fname, include); |
@@ -502,14 +1302,15 @@ static void parse_inc(const char *include, const char *fname) | |||
502 | 1302 | ||
503 | /* find from "-I include" specified directories */ | 1303 | /* find from "-I include" specified directories */ |
504 | free(ap); | 1304 | free(ap); |
505 | /* lo->data has absolute pathname */ | 1305 | /* lo->data have absolute pathname */ |
506 | ap = bb_asprint("%s/%s", lo->data, include); | 1306 | ap = bb_asprint("%s/%s", lo->data, include); |
507 | lo = lo->link; | 1307 | lo = lo->link; |
508 | } | 1308 | } |
509 | 1309 | ||
510 | cur = xmalloc(sizeof(bb_key_t)); | 1310 | cur = xmalloc(sizeof(bb_key_t)); |
511 | cur->keyname = cur->stored_path = ap; | 1311 | cur->keyname = ap; |
512 | cur->key_sz = key_sz; | 1312 | cur->key_sz = key_sz; |
1313 | cur->stored_path = ap; | ||
513 | cur->value = cur->checked = p_i; | 1314 | cur->value = cur->checked = p_i; |
514 | if(p_i == NULL && noiwarning) | 1315 | if(p_i == NULL && noiwarning) |
515 | fprintf(stderr, "%s: Warning: #include \"%s\" not found\n", fname, include); | 1316 | fprintf(stderr, "%s: Warning: #include \"%s\" not found\n", fname, include); |
@@ -528,7 +1329,7 @@ static void parse_conf_opt(const char *opt, const char *val, size_t key_sz) | |||
528 | 1329 | ||
529 | cur = check_key(key_top, opt, key_sz); | 1330 | cur = check_key(key_top, opt, key_sz); |
530 | if(cur != NULL) { | 1331 | if(cur != NULL) { |
531 | /* already present */ | 1332 | /* present already */ |
532 | cur->checked = NULL; /* store only */ | 1333 | cur->checked = NULL; /* store only */ |
533 | if(cur->value == NULL && val == NULL) | 1334 | if(cur->value == NULL && val == NULL) |
534 | return; | 1335 | return; |
@@ -568,7 +1369,7 @@ static void parse_conf_opt(const char *opt, const char *val, size_t key_sz) | |||
568 | first_chars[(int)*k] = *k; | 1369 | first_chars[(int)*k] = *k; |
569 | 1370 | ||
570 | cur->stored_path = k = bb_asprint("%s/%s.h", kp, k); | 1371 | cur->stored_path = k = bb_asprint("%s/%s.h", kp, k); |
571 | /* key conversion [A-Z_] -> [a-z/] */ | 1372 | /* key converting [A-Z_] -> [a-z/] */ |
572 | for(p = k + kp_len + 1; *p; p++) { | 1373 | for(p = k + kp_len + 1; *p; p++) { |
573 | if(*p >= 'A' && *p <= 'Z') | 1374 | if(*p >= 'A' && *p <= 'Z') |
574 | *p = *p - 'A' + 'a'; | 1375 | *p = *p - 'A' + 'a'; |
@@ -604,7 +1405,7 @@ static void store_keys(void) | |||
604 | } | 1405 | } |
605 | /* size_t -> ssize_t :( */ | 1406 | /* size_t -> ssize_t :( */ |
606 | rw_ret = (ssize_t)recordsz; | 1407 | rw_ret = (ssize_t)recordsz; |
607 | /* check kp/key.h, compare after previous use */ | 1408 | /* check kp/key.h, compare after previous usage */ |
608 | cmp_ok = 0; | 1409 | cmp_ok = 0; |
609 | k = cur->stored_path; | 1410 | k = cur->stored_path; |
610 | if(stat(k, &st)) { | 1411 | if(stat(k, &st)) { |
@@ -709,7 +1510,7 @@ parse_chd(const char *fe, const char *p, size_t dirlen) | |||
709 | } | 1510 | } |
710 | } | 1511 | } |
711 | /* direntry is *.[ch] regular file and is not configs */ | 1512 | /* direntry is *.[ch] regular file and is not configs */ |
712 | c_lex(fp, st.st_size); | 1513 | c_lex_src(fp, st.st_size); |
713 | if(!dontgenerate_dep) { | 1514 | if(!dontgenerate_dep) { |
714 | int first; | 1515 | int first; |
715 | if(*e == 'c') { | 1516 | if(*e == 'c') { |
@@ -740,7 +1541,7 @@ parse_chd(const char *fe, const char *p, size_t dirlen) | |||
740 | return NULL; | 1541 | return NULL; |
741 | } | 1542 | } |
742 | 1543 | ||
743 | /* from libbb but inlined for speed considerations */ | 1544 | /* from libbb but inline for fast */ |
744 | static inline llist_t *llist_add_to(llist_t *old_head, char *new_item) | 1545 | static inline llist_t *llist_add_to(llist_t *old_head, char *new_item) |
745 | { | 1546 | { |
746 | llist_t *new_head; | 1547 | llist_t *new_head; |
@@ -763,7 +1564,7 @@ static void scan_dir_find_ch_files(const char *p) | |||
763 | 1564 | ||
764 | dirs = llist_add_to(NULL, bb_simplify_path(p)); | 1565 | dirs = llist_add_to(NULL, bb_simplify_path(p)); |
765 | replace = strlen(dirs->data); | 1566 | replace = strlen(dirs->data); |
766 | /* emulate recursion */ | 1567 | /* emulate recursive */ |
767 | while(dirs) { | 1568 | while(dirs) { |
768 | d_add = NULL; | 1569 | d_add = NULL; |
769 | while(dirs) { | 1570 | while(dirs) { |
@@ -803,7 +1604,7 @@ int main(int argc, char **argv) | |||
803 | llist_t *fl; | 1604 | llist_t *fl; |
804 | 1605 | ||
805 | { | 1606 | { |
806 | /* for bb_simplify_path, this program has no chdir() */ | 1607 | /* for bb_simplify_path, this program have not chdir() */ |
807 | /* libbb-like my xgetcwd() */ | 1608 | /* libbb-like my xgetcwd() */ |
808 | unsigned path_max = 512; | 1609 | unsigned path_max = 512; |
809 | 1610 | ||
@@ -863,7 +1664,7 @@ int main(int argc, char **argv) | |||
863 | for(i = 0; i < UCHAR_MAX; i++) { | 1664 | for(i = 0; i < UCHAR_MAX; i++) { |
864 | if(ISALNUM(i)) | 1665 | if(ISALNUM(i)) |
865 | isalnums[i] = i; | 1666 | isalnums[i] = i; |
866 | /* set unparsed chars to speed up the parser */ | 1667 | /* set unparsed chars for speed up of parser */ |
867 | else if(i != CHR && i != STR && i != POUND && i != REM) | 1668 | else if(i != CHR && i != STR && i != POUND && i != REM) |
868 | first_chars[i] = ANY; | 1669 | first_chars[i] = ANY; |
869 | } | 1670 | } |
@@ -875,7 +1676,7 @@ int main(int argc, char **argv) | |||
875 | 1676 | ||
876 | if(stat(fl->data, &st)) | 1677 | if(stat(fl->data, &st)) |
877 | bb_error_d("stat(%s): %m", fl->data); | 1678 | bb_error_d("stat(%s): %m", fl->data); |
878 | c_lex(fl->data, st.st_size); | 1679 | c_lex_config(fl->data, st.st_size); |
879 | free(fl->data); | 1680 | free(fl->data); |
880 | /* trick for fast comparing found files with configs */ | 1681 | /* trick for fast comparing found files with configs */ |
881 | fl->data = xmalloc(sizeof(struct stat)); | 1682 | fl->data = xmalloc(sizeof(struct stat)); |
@@ -883,7 +1684,6 @@ int main(int argc, char **argv) | |||
883 | } | 1684 | } |
884 | 1685 | ||
885 | /* main loop */ | 1686 | /* main loop */ |
886 | mode = SOURCES_MODE; | ||
887 | argv += optind; | 1687 | argv += optind; |
888 | if(*argv) { | 1688 | if(*argv) { |
889 | while(*argv) | 1689 | while(*argv) |
@@ -923,6 +1723,7 @@ static char *bb_asprint(const char *format, ...) | |||
923 | } | 1723 | } |
924 | 1724 | ||
925 | /* partial libbb routine as is */ | 1725 | /* partial libbb routine as is */ |
1726 | |||
926 | static char *bb_simplify_path(const char *path) | 1727 | static char *bb_simplify_path(const char *path) |
927 | { | 1728 | { |
928 | char *s, *start, *p; | 1729 | char *s, *start, *p; |
@@ -930,7 +1731,7 @@ static char *bb_simplify_path(const char *path) | |||
930 | if (path[0] == '/') | 1731 | if (path[0] == '/') |
931 | start = bb_xstrdup(path); | 1732 | start = bb_xstrdup(path); |
932 | else { | 1733 | else { |
933 | /* is not libbb, but this program has no chdir() */ | 1734 | /* is not libbb, but this program have not chdir() */ |
934 | start = bb_asprint("%s/%s", pwd, path); | 1735 | start = bb_asprint("%s/%s", pwd, path); |
935 | } | 1736 | } |
936 | p = s = start; | 1737 | p = s = start; |