History

added correct ## handling : added TOK_PPNUM token

bellard committed 24 years ago

Commit c0180c41 parent 973eb601 file · +163 −89Browse files

Unified · Split

tcc.c+163−89
@@ -463,6 +463,7 @@ struct TCCState { · 462 unmodified lines
463#define TOK_ARROW 0xcb463#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
1030static inline int toup(int c)1031static 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 else1035 else
1035 return ch;1036 return c;
1036}1037}
1037 1038
1038static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)1039static 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 LIBTCC1089#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
2328void parse_number(void)2337/* parse number in null terminated string 'p' and return it in the
2338 current token */
2339void 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 */
2603static inline void next_nomacro1(void)2606static 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 */
2828static 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 */
2835static int *macro_twosharps(void)2865static 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(&macro_str1);2876 tok_str_new(&macro_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(&macro_ptr, &cval);2887 t = tok_get(&macro_ptr, &cval);
2856 /* XXX: not exact, but cannot do more without2888
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(&macro_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(&macro_str1, tok, &tokc);2965 tok_str_add2(&macro_str1, tok, &tokc);
2898 }2966 }
2967 cstr_free(&cstr);
2899 tok_str_add(&macro_str1, 0);2968 tok_str_add(&macro_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));