Unified · Split
| @@ -463,6 +463,7 @@ struct TCCState { · 462 unmodified lines | |||
| 463 | #define TOK_ARROW 0xcb | 463 | #define TOK_ARROW 0xcb |
| 464 | #define TOK_DOTS 0xcc /* three dots */ | 464 | #define TOK_DOTS 0xcc /* three dots */ |
| 465 | #define TOK_SHR 0xcd /* unsigned shift right */ | 465 | #define TOK_SHR 0xcd /* unsigned shift right */ |
| 466 | #define TOK_PPNUM 0xce /* preprocessor number */ | ||
| 466 | 467 | ||
| 467 | #define TOK_SHL 0x01 /* shift left */ | 468 | #define TOK_SHL 0x01 /* shift left */ |
| 468 | #define TOK_SAR 0x02 /* signed shift right */ | 469 | #define TOK_SAR 0x02 /* signed shift right */ |
| @@ -1029,10 +1030,10 @@ static inline int isoct(int c) · 560 unmodified lines | |||
| 1029 | 1030 | ||
| 1030 | static inline int toup(int c) | 1031 | static inline int toup(int c) |
| 1031 | { | 1032 | { |
| 1032 | if (ch >= 'a' && ch <= 'z') | 1033 | if (c >= 'a' && c <= 'z') |
| 1033 | return ch - 'a' + 'A'; | 1034 | return c - 'a' + 'A'; |
| 1034 | else | 1035 | else |
| 1035 | return ch; | 1036 | return c; |
| 1036 | } | 1037 | } |
| 1037 | 1038 | ||
| 1038 | static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap) | 1039 | static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap) |
| @@ -1081,7 +1082,8 @@ void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) · 42 unmodified lines | |||
| 1081 | } else { | 1082 | } else { |
| 1082 | s1->error_func(s1->error_opaque, buf); | 1083 | s1->error_func(s1->error_opaque, buf); |
| 1083 | } | 1084 | } |
| 1084 | s1->nb_errors++; | 1085 | if (!is_warning) |
| 1086 | s1->nb_errors++; | ||
| 1085 | } | 1087 | } |
| 1086 | 1088 | ||
| 1087 | #ifdef LIBTCC | 1089 | #ifdef LIBTCC |
| @@ -1314,6 +1316,12 @@ char *get_tok_str(int v, CValue *cv) · 226 unmodified lines | |||
| 1314 | cstr_ccat(&cstr_buf, '\''); | 1316 | cstr_ccat(&cstr_buf, '\''); |
| 1315 | cstr_ccat(&cstr_buf, '\0'); | 1317 | cstr_ccat(&cstr_buf, '\0'); |
| 1316 | break; | 1318 | break; |
| 1319 | case TOK_PPNUM: | ||
| 1320 | cstr = cv->cstr; | ||
| 1321 | len = cstr->size - 1; | ||
| 1322 | for(i=0;i<len;i++) | ||
| 1323 | add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]); | ||
| 1324 | break; | ||
| 1317 | case TOK_STR: | 1325 | case TOK_STR: |
| 1318 | case TOK_LSTR: | 1326 | case TOK_LSTR: |
| 1319 | cstr = cv->cstr; | 1327 | cstr = cv->cstr; |
| @@ -1724,6 +1732,7 @@ static inline int tok_ext_size(int t) · 404 unmodified lines | |||
| 1724 | case TOK_LSTR: | 1732 | case TOK_LSTR: |
| 1725 | case TOK_CFLOAT: | 1733 | case TOK_CFLOAT: |
| 1726 | case TOK_LINENUM: | 1734 | case TOK_LINENUM: |
| 1735 | case TOK_PPNUM: | ||
| 1727 | return 1; | 1736 | return 1; |
| 1728 | case TOK_CDOUBLE: | 1737 | case TOK_CDOUBLE: |
| 1729 | case TOK_CLLONG: | 1738 | case TOK_CLLONG: |
| @@ -1756,7 +1765,7 @@ static void tok_str_free(int *str) · 26 unmodified lines | |||
| 1756 | t = *p++; | 1765 | t = *p++; |
| 1757 | if (t == 0) | 1766 | if (t == 0) |
| 1758 | break; | 1767 | break; |
| 1759 | if (t == TOK_STR || t == TOK_LSTR) { | 1768 | if (t == TOK_STR || t == TOK_LSTR || t == TOK_PPNUM) { |
| 1760 | /* XXX: use a macro to be portable on 64 bit ? */ | 1769 | /* XXX: use a macro to be portable on 64 bit ? */ |
| 1761 | cstr = (CString *)(*p++); | 1770 | cstr = (CString *)(*p++); |
| 1762 | cstr_free(cstr); | 1771 | cstr_free(cstr); |
| @@ -1791,7 +1800,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) · 28 unmodified lines | |||
| 1791 | CValue cv1; | 1800 | CValue cv1; |
| 1792 | 1801 | ||
| 1793 | tok_str_add(s, t); | 1802 | tok_str_add(s, t); |
| 1794 | if (t == TOK_STR || t == TOK_LSTR) { | 1803 | if (t == TOK_STR || t == TOK_LSTR || t == TOK_PPNUM) { |
| 1795 | /* special case: need to duplicate string */ | 1804 | /* special case: need to duplicate string */ |
| 1796 | cstr1 = cv->cstr; | 1805 | cstr1 = cv->cstr; |
| 1797 | cstr = tcc_malloc(sizeof(CString)); | 1806 | cstr = tcc_malloc(sizeof(CString)); |
| @@ -2325,42 +2334,32 @@ void bn_zero(unsigned int *bn) · 527 unmodified lines | |||
| 2325 | } | 2334 | } |
| 2326 | } | 2335 | } |
| 2327 | 2336 | ||
| 2328 | void parse_number(void) | 2337 | /* parse number in null terminated string 'p' and return it in the |
| 2338 | current token */ | ||
| 2339 | void parse_number(const char *p) | ||
| 2329 | { | 2340 | { |
| 2330 | int b, t, shift, frac_bits, s, exp_val; | 2341 | int b, t, shift, frac_bits, s, exp_val, ch; |
| 2331 | char *q; | 2342 | char *q; |
| 2332 | unsigned int bn[BN_SIZE]; | 2343 | unsigned int bn[BN_SIZE]; |
| 2333 | double d; | 2344 | double d; |
| 2334 | 2345 | ||
| 2335 | /* number */ | 2346 | /* number */ |
| 2336 | q = token_buf; | 2347 | q = token_buf; |
| 2348 | ch = *p++; | ||
| 2337 | t = ch; | 2349 | t = ch; |
| 2338 | cinp(); | 2350 | ch = *p++; |
| 2339 | *q++ = t; | 2351 | *q++ = t; |
| 2340 | b = 10; | 2352 | b = 10; |
| 2341 | if (t == '.') { | 2353 | if (t == '.') { |
| 2342 | /* special dot handling */ | 2354 | goto float_frac_parse; |
| 2343 | if (ch >= '0' && ch <= '9') { | ||
| 2344 | goto float_frac_parse; | ||
| 2345 | } else if (ch == '.') { | ||
| 2346 | cinp(); | ||
| 2347 | if (ch != '.') | ||
| 2348 | expect("'.'"); | ||
| 2349 | cinp(); | ||
| 2350 | tok = TOK_DOTS; | ||
| 2351 | } else { | ||
| 2352 | /* dots */ | ||
| 2353 | tok = t; | ||
| 2354 | } | ||
| 2355 | return; | ||
| 2356 | } else if (t == '0') { | 2355 | } else if (t == '0') { |
| 2357 | if (ch == 'x' || ch == 'X') { | 2356 | if (ch == 'x' || ch == 'X') { |
| 2358 | q--; | 2357 | q--; |
| 2359 | cinp(); | 2358 | ch = *p++; |
| 2360 | b = 16; | 2359 | b = 16; |
| 2361 | } else if (tcc_ext && (ch == 'b' || ch == 'B')) { | 2360 | } else if (tcc_ext && (ch == 'b' || ch == 'B')) { |
| 2362 | q--; | 2361 | q--; |
| 2363 | cinp(); | 2362 | ch = *p++; |
| 2364 | b = 2; | 2363 | b = 2; |
| 2365 | } | 2364 | } |
| 2366 | } | 2365 | } |
| @@ -2382,7 +2381,7 @@ void parse_number(void) · 15 unmodified lines | |||
| 2382 | error("number too long"); | 2381 | error("number too long"); |
| 2383 | } | 2382 | } |
| 2384 | *q++ = ch; | 2383 | *q++ = ch; |
| 2385 | cinp(); | 2384 | ch = *p++; |
| 2386 | } | 2385 | } |
| 2387 | if (ch == '.' || | 2386 | if (ch == '.' || |
| 2388 | ((ch == 'e' || ch == 'E') && b == 10) || | 2387 | ((ch == 'e' || ch == 'E') && b == 10) || |
| @@ -2415,7 +2414,7 @@ void parse_number(void) · 26 unmodified lines | |||
| 2415 | } | 2414 | } |
| 2416 | frac_bits = 0; | 2415 | frac_bits = 0; |
| 2417 | if (ch == '.') { | 2416 | if (ch == '.') { |
| 2418 | cinp(); | 2417 | ch = *p++; |
| 2419 | while (1) { | 2418 | while (1) { |
| 2420 | t = ch; | 2419 | t = ch; |
| 2421 | if (t >= 'a' && t <= 'f') { | 2420 | if (t >= 'a' && t <= 'f') { |
| @@ -2431,25 +2430,25 @@ void parse_number(void) · 9 unmodified lines | |||
| 2431 | error("invalid digit"); | 2430 | error("invalid digit"); |
| 2432 | bn_lshift(bn, shift, t); | 2431 | bn_lshift(bn, shift, t); |
| 2433 | frac_bits += shift; | 2432 | frac_bits += shift; |
| 2434 | cinp(); | 2433 | ch = *p++; |
| 2435 | } | 2434 | } |
| 2436 | } | 2435 | } |
| 2437 | if (ch != 'p' && ch != 'P') | 2436 | if (ch != 'p' && ch != 'P') |
| 2438 | error("exponent expected"); | 2437 | error("exponent expected"); |
| 2439 | cinp(); | 2438 | ch = *p++; |
| 2440 | s = 1; | 2439 | s = 1; |
| 2441 | exp_val = 0; | 2440 | exp_val = 0; |
| 2442 | if (ch == '+') { | 2441 | if (ch == '+') { |
| 2443 | cinp(); | 2442 | ch = *p++; |
| 2444 | } else if (ch == '-') { | 2443 | } else if (ch == '-') { |
| 2445 | s = -1; | 2444 | s = -1; |
| 2446 | cinp(); | 2445 | ch = *p++; |
| 2447 | } | 2446 | } |
| 2448 | if (ch < '0' || ch > '9') | 2447 | if (ch < '0' || ch > '9') |
| 2449 | error("exponent digits expected"); | 2448 | error("exponent digits expected"); |
| 2450 | while (ch >= '0' && ch <= '9') { | 2449 | while (ch >= '0' && ch <= '9') { |
| 2451 | exp_val = exp_val * 10 + ch - '0'; | 2450 | exp_val = exp_val * 10 + ch - '0'; |
| 2452 | cinp(); | 2451 | ch = *p++; |
| 2453 | } | 2452 | } |
| 2454 | exp_val = exp_val * s; | 2453 | exp_val = exp_val * s; |
| 2455 | 2454 | ||
| @@ -2459,12 +2458,12 @@ void parse_number(void) · 3 unmodified lines | |||
| 2459 | d = ldexp(d, exp_val - frac_bits); | 2458 | d = ldexp(d, exp_val - frac_bits); |
| 2460 | t = toup(ch); | 2459 | t = toup(ch); |
| 2461 | if (t == 'F') { | 2460 | if (t == 'F') { |
| 2462 | cinp(); | 2461 | ch = *p++; |
| 2463 | tok = TOK_CFLOAT; | 2462 | tok = TOK_CFLOAT; |
| 2464 | /* float : should handle overflow */ | 2463 | /* float : should handle overflow */ |
| 2465 | tokc.f = (float)d; | 2464 | tokc.f = (float)d; |
| 2466 | } else if (t == 'L') { | 2465 | } else if (t == 'L') { |
| 2467 | cinp(); | 2466 | ch = *p++; |
| 2468 | tok = TOK_CLDOUBLE; | 2467 | tok = TOK_CLDOUBLE; |
| 2469 | /* XXX: not large enough */ | 2468 | /* XXX: not large enough */ |
| 2470 | tokc.ld = (long double)d; | 2469 | tokc.ld = (long double)d; |
| @@ -2478,25 +2477,25 @@ void parse_number(void) · 7 unmodified lines | |||
| 2478 | if (q >= token_buf + STRING_MAX_SIZE) | 2477 | if (q >= token_buf + STRING_MAX_SIZE) |
| 2479 | goto num_too_long; | 2478 | goto num_too_long; |
| 2480 | *q++ = ch; | 2479 | *q++ = ch; |
| 2481 | cinp(); | 2480 | ch = *p++; |
| 2482 | float_frac_parse: | 2481 | float_frac_parse: |
| 2483 | while (ch >= '0' && ch <= '9') { | 2482 | while (ch >= '0' && ch <= '9') { |
| 2484 | if (q >= token_buf + STRING_MAX_SIZE) | 2483 | if (q >= token_buf + STRING_MAX_SIZE) |
| 2485 | goto num_too_long; | 2484 | goto num_too_long; |
| 2486 | *q++ = ch; | 2485 | *q++ = ch; |
| 2487 | cinp(); | 2486 | ch = *p++; |
| 2488 | } | 2487 | } |
| 2489 | } | 2488 | } |
| 2490 | if (ch == 'e' || ch == 'E') { | 2489 | if (ch == 'e' || ch == 'E') { |
| 2491 | if (q >= token_buf + STRING_MAX_SIZE) | 2490 | if (q >= token_buf + STRING_MAX_SIZE) |
| 2492 | goto num_too_long; | 2491 | goto num_too_long; |
| 2493 | *q++ = ch; | 2492 | *q++ = ch; |
| 2494 | cinp(); | 2493 | ch = *p++; |
| 2495 | if (ch == '-' || ch == '+') { | 2494 | if (ch == '-' || ch == '+') { |
| 2496 | if (q >= token_buf + STRING_MAX_SIZE) | 2495 | if (q >= token_buf + STRING_MAX_SIZE) |
| 2497 | goto num_too_long; | 2496 | goto num_too_long; |
| 2498 | *q++ = ch; | 2497 | *q++ = ch; |
| 2499 | cinp(); | 2498 | ch = *p++; |
| 2500 | } | 2499 | } |
| 2501 | if (ch < '0' || ch > '9') | 2500 | if (ch < '0' || ch > '9') |
| 2502 | error("exponent digits expected"); | 2501 | error("exponent digits expected"); |
| @@ -2504,18 +2503,18 @@ void parse_number(void) · 1 unmodified line | |||
| 2504 | if (q >= token_buf + STRING_MAX_SIZE) | 2503 | if (q >= token_buf + STRING_MAX_SIZE) |
| 2505 | goto num_too_long; | 2504 | goto num_too_long; |
| 2506 | *q++ = ch; | 2505 | *q++ = ch; |
| 2507 | cinp(); | 2506 | ch = *p++; |
| 2508 | } | 2507 | } |
| 2509 | } | 2508 | } |
| 2510 | *q = '\0'; | 2509 | *q = '\0'; |
| 2511 | t = toup(ch); | 2510 | t = toup(ch); |
| 2512 | errno = 0; | 2511 | errno = 0; |
| 2513 | if (t == 'F') { | 2512 | if (t == 'F') { |
| 2514 | cinp(); | 2513 | ch = *p++; |
| 2515 | tok = TOK_CFLOAT; | 2514 | tok = TOK_CFLOAT; |
| 2516 | tokc.f = strtof(token_buf, NULL); | 2515 | tokc.f = strtof(token_buf, NULL); |
| 2517 | } else if (t == 'L') { | 2516 | } else if (t == 'L') { |
| 2518 | cinp(); | 2517 | ch = *p++; |
| 2519 | tok = TOK_CLDOUBLE; | 2518 | tok = TOK_CLDOUBLE; |
| 2520 | tokc.ld = strtold(token_buf, NULL); | 2519 | tokc.ld = strtold(token_buf, NULL); |
| 2521 | } else { | 2520 | } else { |
| @@ -2525,7 +2524,7 @@ void parse_number(void) · 3 unmodified lines | |||
| 2525 | } | 2524 | } |
| 2526 | } else { | 2525 | } else { |
| 2527 | unsigned long long n, n1; | 2526 | unsigned long long n, n1; |
| 2528 | int lcount; | 2527 | int lcount, ucount; |
| 2529 | 2528 | ||
| 2530 | /* integer number */ | 2529 | /* integer number */ |
| 2531 | *q = '\0'; | 2530 | *q = '\0'; |
| @@ -2552,6 +2551,7 @@ void parse_number(void) · 20 unmodified lines | |||
| 2552 | n1 = n; | 2551 | n1 = n; |
| 2553 | n = n * b + t; | 2552 | n = n * b + t; |
| 2554 | /* detect overflow */ | 2553 | /* detect overflow */ |
| 2554 | /* XXX: this test is not reliable */ | ||
| 2555 | if (n < n1) | 2555 | if (n < n1) |
| 2556 | error("integer constant overflow"); | 2556 | error("integer constant overflow"); |
| 2557 | } | 2557 | } |
| @@ -2568,11 +2568,12 @@ void parse_number(void) · 10 unmodified lines | |||
| 2568 | tok = TOK_CINT; | 2568 | tok = TOK_CINT; |
| 2569 | } | 2569 | } |
| 2570 | lcount = 0; | 2570 | lcount = 0; |
| 2571 | ucount = 0; | ||
| 2571 | for(;;) { | 2572 | for(;;) { |
| 2572 | t = toup(ch); | 2573 | t = toup(ch); |
| 2573 | if (t == 'L') { | 2574 | if (t == 'L') { |
| 2574 | if (lcount >= 2) | 2575 | if (lcount >= 2) |
| 2575 | error("three 'l' in integer constant"); | 2576 | error("three 'l's in integer constant"); |
| 2576 | lcount++; | 2577 | lcount++; |
| 2577 | if (lcount == 2) { | 2578 | if (lcount == 2) { |
| 2578 | if (tok == TOK_CINT) | 2579 | if (tok == TOK_CINT) |
| @@ -2580,13 +2581,16 @@ void parse_number(void) · 1 unmodified line | |||
| 2580 | else if (tok == TOK_CUINT) | 2581 | else if (tok == TOK_CUINT) |
| 2581 | tok = TOK_CULLONG; | 2582 | tok = TOK_CULLONG; |
| 2582 | } | 2583 | } |
| 2583 | cinp(); | 2584 | ch = *p++; |
| 2584 | } else if (t == 'U') { | 2585 | } else if (t == 'U') { |
| 2586 | if (ucount >= 1) | ||
| 2587 | error("two 'u's in integer constant"); | ||
| 2588 | ucount++; | ||
| 2585 | if (tok == TOK_CINT) | 2589 | if (tok == TOK_CINT) |
| 2586 | tok = TOK_CUINT; | 2590 | tok = TOK_CUINT; |
| 2587 | else if (tok == TOK_CLLONG) | 2591 | else if (tok == TOK_CLLONG) |
| 2588 | tok = TOK_CULLONG; | 2592 | tok = TOK_CULLONG; |
| 2589 | cinp(); | 2593 | ch = *p++; |
| 2590 | } else { | 2594 | } else { |
| 2591 | break; | 2595 | break; |
| 2592 | } | 2596 | } |
| @@ -2598,7 +2602,6 @@ void parse_number(void) · 5 unmodified lines | |||
| 2598 | } | 2602 | } |
| 2599 | } | 2603 | } |
| 2600 | 2604 | ||
| 2601 | |||
| 2602 | /* return next token without macro substitution */ | 2605 | /* return next token without macro substitution */ |
| 2603 | static inline void next_nomacro1(void) | 2606 | static inline void next_nomacro1(void) |
| 2604 | { | 2607 | { |
| @@ -2649,8 +2652,42 @@ static inline void next_nomacro1(void) · 44 unmodified lines | |||
| 2649 | *q = '\0'; | 2652 | *q = '\0'; |
| 2650 | ts = tok_alloc(token_buf, q - token_buf); | 2653 | ts = tok_alloc(token_buf, q - token_buf); |
| 2651 | tok = ts->tok; | 2654 | tok = ts->tok; |
| 2652 | } else if (isnum(ch) || ch == '.') { | 2655 | } else if (isnum(ch)) { |
| 2653 | parse_number(); | 2656 | int t; |
| 2657 | cstr_reset(&tokcstr); | ||
| 2658 | /* after the first digit, accept digits, alpha, '.' or sign if | ||
| 2659 | prefixed by 'eEpP' */ | ||
| 2660 | parse_num: | ||
| 2661 | for(;;) { | ||
| 2662 | t = ch; | ||
| 2663 | cstr_ccat(&tokcstr, ch); | ||
| 2664 | cinp(); | ||
| 2665 | if (!(isnum(ch) || isid(ch) || ch == '.' || | ||
| 2666 | ((ch == '+' || ch == '-') && | ||
| 2667 | (t == 'e' || t == 'E' || t == 'p' || t == 'P')))) | ||
| 2668 | break; | ||
| 2669 | } | ||
| 2670 | /* We add a trailing '\0' to ease parsing */ | ||
| 2671 | cstr_ccat(&tokcstr, '\0'); | ||
| 2672 | tokc.cstr = &tokcstr; | ||
| 2673 | tok = TOK_PPNUM; | ||
| 2674 | } else if (ch == '.') { | ||
| 2675 | /* special dot handling because it can also start a number */ | ||
| 2676 | cinp(); | ||
| 2677 | if (isnum(ch)) { | ||
| 2678 | cstr_reset(&tokcstr); | ||
| 2679 | cstr_ccat(&tokcstr, '.'); | ||
| 2680 | goto parse_num; | ||
| 2681 | } | ||
| 2682 | if (ch == '.') { | ||
| 2683 | cinp(); | ||
| 2684 | if (ch != '.') | ||
| 2685 | expect("'.'"); | ||
| 2686 | cinp(); | ||
| 2687 | tok = TOK_DOTS; | ||
| 2688 | } else { | ||
| 2689 | tok = '.'; | ||
| 2690 | } | ||
| 2654 | } else if (ch == '\'') { | 2691 | } else if (ch == '\'') { |
| 2655 | tok = TOK_CCHAR; | 2692 | tok = TOK_CCHAR; |
| 2656 | char_const: | 2693 | char_const: |
| @@ -2824,13 +2861,6 @@ int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) · 167 unmodified lines | |||
| 2824 | return str.str; | 2861 | return str.str; |
| 2825 | } | 2862 | } |
| 2826 | 2863 | ||
| 2827 | /* not inline to save space */ | ||
| 2828 | static int is_tok_num(int t) | ||
| 2829 | { | ||
| 2830 | return (t == TOK_CINT || t == TOK_CUINT || | ||
| 2831 | t == TOK_CLLONG || t == TOK_CULLONG); | ||
| 2832 | } | ||
| 2833 | |||
| 2834 | /* handle the '##' operator */ | 2864 | /* handle the '##' operator */ |
| 2835 | static int *macro_twosharps(void) | 2865 | static int *macro_twosharps(void) |
| 2836 | { | 2866 | { |
| @@ -2840,7 +2870,9 @@ static int *macro_twosharps(void) · 3 unmodified lines | |||
| 2840 | const char *p1, *p2; | 2870 | const char *p1, *p2; |
| 2841 | CValue cval; | 2871 | CValue cval; |
| 2842 | TokenString macro_str1; | 2872 | TokenString macro_str1; |
| 2843 | 2873 | CString cstr; | |
| 2874 | |||
| 2875 | cstr_new(&cstr); | ||
| 2844 | tok_str_new(¯o_str1); | 2876 | tok_str_new(¯o_str1); |
| 2845 | tok = 0; | 2877 | tok = 0; |
| 2846 | while (1) { | 2878 | while (1) { |
| @@ -2853,49 +2885,86 @@ static int *macro_twosharps(void) · 6 unmodified lines | |||
| 2853 | t = *macro_ptr; | 2885 | t = *macro_ptr; |
| 2854 | if (t) { | 2886 | if (t) { |
| 2855 | t = tok_get(¯o_ptr, &cval); | 2887 | t = tok_get(¯o_ptr, &cval); |
| 2856 | /* XXX: not exact, but cannot do more without | 2888 | |
| 2857 | modifying the whole preprocessing architecture ! */ | 2889 | /* We concatenate the two tokens if we have an |
| 2858 | /* XXX: handle arbitrary size */ | 2890 | identifier or a preprocessing number */ |
| 2891 | cstr_reset(&cstr); | ||
| 2859 | p1 = get_tok_str(tok, &tokc); | 2892 | p1 = get_tok_str(tok, &tokc); |
| 2860 | pstrcpy(token_buf, sizeof(token_buf), p1); | 2893 | cstr_cat(&cstr, p1); |
| 2861 | p2 = get_tok_str(t, &cval); | 2894 | p2 = get_tok_str(t, &cval); |
| 2862 | if (tok >= TOK_IDENT && | 2895 | cstr_cat(&cstr, p2); |
| 2863 | (t >= TOK_IDENT || is_tok_num(t))) { | 2896 | cstr_ccat(&cstr, '\0'); |
| 2864 | pstrcat(token_buf, sizeof(token_buf), p2); | 2897 | |
| 2865 | ts = tok_alloc(token_buf, strlen(token_buf)); | 2898 | if ((tok >= TOK_IDENT || tok == TOK_PPNUM) && |
| 2866 | tok = ts->tok; /* modify current token */ | 2899 | (t >= TOK_IDENT || t == TOK_PPNUM)) { |
| 2867 | } else if (is_tok_num(tok) && is_tok_num(t)) { | 2900 | if (tok == TOK_PPNUM) { |
| 2868 | unsigned long long n; | 2901 | /* if number, then create a number token */ |
| 2869 | do_num: | 2902 | /* NOTE: no need to allocate because |
| 2870 | pstrcat(token_buf, sizeof(token_buf), p2); | 2903 | tok_str_add2() does it */ |
| 2871 | n = strtoull(token_buf, NULL, 10); | 2904 | tokc.cstr = &cstr; |
| 2872 | if ((n & 0xffffffff00000000LL) != 0) { | ||
| 2873 | if ((n >> 63) != 0) | ||
| 2874 | tok = TOK_CULLONG; | ||
| 2875 | else | ||
| 2876 | tok = TOK_CLLONG; | ||
| 2877 | } else if (n > 0x7fffffff) { | ||
| 2878 | tok = TOK_CUINT; | ||
| 2879 | } else { | 2905 | } else { |
| 2880 | tok = TOK_CINT; | 2906 | /* if identifier, we must do a test to |
| 2907 | validate we have a correct identifier */ | ||
| 2908 | if (t == TOK_PPNUM) { | ||
| 2909 | const char *p; | ||
| 2910 | int c; | ||
| 2911 | |||
| 2912 | p = p2; | ||
| 2913 | for(;;) { | ||
| 2914 | c = *p; | ||
| 2915 | if (c == '\0') | ||
| 2916 | break; | ||
| 2917 | p++; | ||
| 2918 | if (!isnum(c) && !isid(c)) | ||
| 2919 | goto error_pasting; | ||
| 2920 | } | ||
| 2921 | } | ||
| 2922 | ts = tok_alloc(cstr.data, strlen(cstr.data)); | ||
| 2923 | tok = ts->tok; /* modify current token */ | ||
| 2881 | } | 2924 | } |
| 2882 | if (tok == TOK_CINT || tok == TOK_CUINT) | ||
| 2883 | tokc.ui = n; | ||
| 2884 | else | ||
| 2885 | tokc.ull = n; | ||
| 2886 | } else if (is_tok_num(tok) && t >= TOK_IDENT) { | ||
| 2887 | /* incorrect, but suffisant for '1LL' case */ | ||
| 2888 | goto do_num; | ||
| 2889 | } else { | 2925 | } else { |
| 2890 | warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", token_buf, p2); | 2926 | const char *str = cstr.data; |
| 2891 | /* cannot merge tokens: skip '##' */ | 2927 | const unsigned char *q; |
| 2892 | macro_ptr = macro_ptr1; | 2928 | |
| 2893 | break; | 2929 | /* we look for a valid token */ |
| 2930 | /* XXX: do more extensive checks */ | ||
| 2931 | if (!strcmp(str, ">>=")) { | ||
| 2932 | tok = TOK_A_SAR; | ||
| 2933 | } else if (!strcmp(str, "<<=")) { | ||
| 2934 | tok = TOK_A_SHL; | ||
| 2935 | } else if (strlen(str) == 2) { | ||
| 2936 | /* search in two bytes table */ | ||
| 2937 | q = tok_two_chars; | ||
| 2938 | for(;;) { | ||
| 2939 | if (!*q) | ||
| 2940 | goto error_pasting; | ||
| 2941 | if (q[0] == str[0] && q[1] == str[1]) | ||
| 2942 | break; | ||
| 2943 | q += 3; | ||
| 2944 | } | ||
| 2945 | tok = q[2]; | ||
| 2946 | } else { | ||
| 2947 | error_pasting: | ||
| 2948 | /* NOTE: because get_tok_str use a static buffer, | ||
| 2949 | we must save it */ | ||
| 2950 | cstr_reset(&cstr); | ||
| 2951 | p1 = get_tok_str(tok, &tokc); | ||
| 2952 | cstr_cat(&cstr, p1); | ||
| 2953 | cstr_ccat(&cstr, '\0'); | ||
| 2954 | p2 = get_tok_str(t, &cval); | ||
| 2955 | warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2); | ||
| 2956 | /* cannot merge tokens: just add them separately */ | ||
| 2957 | tok_str_add2(¯o_str1, tok, &tokc); | ||
| 2958 | /* XXX: free associated memory ? */ | ||
| 2959 | tok = t; | ||
| 2960 | tokc = cval; | ||
| 2961 | } | ||
| 2894 | } | 2962 | } |
| 2895 | } | 2963 | } |
| 2896 | } | 2964 | } |
| 2897 | tok_str_add2(¯o_str1, tok, &tokc); | 2965 | tok_str_add2(¯o_str1, tok, &tokc); |
| 2898 | } | 2966 | } |
| 2967 | cstr_free(&cstr); | ||
| 2899 | tok_str_add(¯o_str1, 0); | 2968 | tok_str_add(¯o_str1, 0); |
| 2900 | return macro_str1.str; | 2969 | return macro_str1.str; |
| 2901 | } | 2970 | } |
| @@ -3100,6 +3169,11 @@ void next(void) · 198 unmodified lines | |||
| 3100 | goto redo; | 3169 | goto redo; |
| 3101 | } | 3170 | } |
| 3102 | } | 3171 | } |
| 3172 | |||
| 3173 | /* convert preprocessor tokens into C tokens */ | ||
| 3174 | if (tok == TOK_PPNUM) { | ||
| 3175 | parse_number((char *)tokc.cstr->data); | ||
| 3176 | } | ||
| 3103 | } | 3177 | } |
| 3104 | #if defined(DEBUG) | 3178 | #if defined(DEBUG) |
| 3105 | printf("token = %s\n", get_tok_str(tok, &tokc)); | 3179 | printf("token = %s\n", get_tok_str(tok, &tokc)); |