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
463463 #define TOK_ARROW 0xcb
464464 #define TOK_DOTS 0xcc /* three dots */
465465 #define TOK_SHR 0xcd /* unsigned shift right */
466+#define TOK_PPNUM 0xce /* preprocessor number */
466467
467468 #define TOK_SHL 0x01 /* shift left */
468469 #define TOK_SAR 0x02 /* signed shift right */
@@ -1029,10 +1030,10 @@ static inline int isoct(int c) · 560 unmodified lines
10291030
10301031 static inline int toup(int c)
10311032 {
1032− if (ch >= 'a' && ch <= 'z')
1033− return ch - 'a' + 'A';
1033+ if (c >= 'a' && c <= 'z')
1034+ return c - 'a' + 'A';
10341035 else
1035− return ch;
1036+ return c;
10361037 }
10371038
10381039 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
10811082 } else {
10821083 s1->error_func(s1->error_opaque, buf);
10831084 }
1084− s1->nb_errors++;
1085+ if (!is_warning)
1086+ s1->nb_errors++;
10851087 }
10861088
10871089 #ifdef LIBTCC
@@ -1314,6 +1316,12 @@ char *get_tok_str(int v, CValue *cv) · 226 unmodified lines
13141316 cstr_ccat(&cstr_buf, '\'');
13151317 cstr_ccat(&cstr_buf, '\0');
13161318 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;
13171325 case TOK_STR:
13181326 case TOK_LSTR:
13191327 cstr = cv->cstr;
@@ -1724,6 +1732,7 @@ static inline int tok_ext_size(int t) · 404 unmodified lines
17241732 case TOK_LSTR:
17251733 case TOK_CFLOAT:
17261734 case TOK_LINENUM:
1735+ case TOK_PPNUM:
17271736 return 1;
17281737 case TOK_CDOUBLE:
17291738 case TOK_CLLONG:
@@ -1756,7 +1765,7 @@ static void tok_str_free(int *str) · 26 unmodified lines
17561765 t = *p++;
17571766 if (t == 0)
17581767 break;
1759− if (t == TOK_STR || t == TOK_LSTR) {
1768+ if (t == TOK_STR || t == TOK_LSTR || t == TOK_PPNUM) {
17601769 /* XXX: use a macro to be portable on 64 bit ? */
17611770 cstr = (CString *)(*p++);
17621771 cstr_free(cstr);
@@ -1791,7 +1800,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) · 28 unmodified lines
17911800 CValue cv1;
17921801
17931802 tok_str_add(s, t);
1794− if (t == TOK_STR || t == TOK_LSTR) {
1803+ if (t == TOK_STR || t == TOK_LSTR || t == TOK_PPNUM) {
17951804 /* special case: need to duplicate string */
17961805 cstr1 = cv->cstr;
17971806 cstr = tcc_malloc(sizeof(CString));
@@ -2325,42 +2334,32 @@ void bn_zero(unsigned int *bn) · 527 unmodified lines
23252334 }
23262335 }
23272336
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)
23292340 {
2330− int b, t, shift, frac_bits, s, exp_val;
2341+ int b, t, shift, frac_bits, s, exp_val, ch;
23312342 char *q;
23322343 unsigned int bn[BN_SIZE];
23332344 double d;
23342345
23352346 /* number */
23362347 q = token_buf;
2348+ ch = *p++;
23372349 t = ch;
2338− cinp();
2350+ ch = *p++;
23392351 *q++ = t;
23402352 b = 10;
23412353 if (t == '.') {
2342− /* special dot handling */
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;
2354+ goto float_frac_parse;
23562355 } else if (t == '0') {
23572356 if (ch == 'x' || ch == 'X') {
23582357 q--;
2359− cinp();
2358+ ch = *p++;
23602359 b = 16;
23612360 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
23622361 q--;
2363− cinp();
2362+ ch = *p++;
23642363 b = 2;
23652364 }
23662365 }
@@ -2382,7 +2381,7 @@ void parse_number(void) · 15 unmodified lines
23822381 error("number too long");
23832382 }
23842383 *q++ = ch;
2385− cinp();
2384+ ch = *p++;
23862385 }
23872386 if (ch == '.' ||
23882387 ((ch == 'e' || ch == 'E') && b == 10) ||
@@ -2415,7 +2414,7 @@ void parse_number(void) · 26 unmodified lines
24152414 }
24162415 frac_bits = 0;
24172416 if (ch == '.') {
2418− cinp();
2417+ ch = *p++;
24192418 while (1) {
24202419 t = ch;
24212420 if (t >= 'a' && t <= 'f') {
@@ -2431,25 +2430,25 @@ void parse_number(void) · 9 unmodified lines
24312430 error("invalid digit");
24322431 bn_lshift(bn, shift, t);
24332432 frac_bits += shift;
2434− cinp();
2433+ ch = *p++;
24352434 }
24362435 }
24372436 if (ch != 'p' && ch != 'P')
24382437 error("exponent expected");
2439− cinp();
2438+ ch = *p++;
24402439 s = 1;
24412440 exp_val = 0;
24422441 if (ch == '+') {
2443− cinp();
2442+ ch = *p++;
24442443 } else if (ch == '-') {
24452444 s = -1;
2446− cinp();
2445+ ch = *p++;
24472446 }
24482447 if (ch < '0' || ch > '9')
24492448 error("exponent digits expected");
24502449 while (ch >= '0' && ch <= '9') {
24512450 exp_val = exp_val * 10 + ch - '0';
2452− cinp();
2451+ ch = *p++;
24532452 }
24542453 exp_val = exp_val * s;
24552454
@@ -2459,12 +2458,12 @@ void parse_number(void) · 3 unmodified lines
24592458 d = ldexp(d, exp_val - frac_bits);
24602459 t = toup(ch);
24612460 if (t == 'F') {
2462− cinp();
2461+ ch = *p++;
24632462 tok = TOK_CFLOAT;
24642463 /* float : should handle overflow */
24652464 tokc.f = (float)d;
24662465 } else if (t == 'L') {
2467− cinp();
2466+ ch = *p++;
24682467 tok = TOK_CLDOUBLE;
24692468 /* XXX: not large enough */
24702469 tokc.ld = (long double)d;
@@ -2478,25 +2477,25 @@ void parse_number(void) · 7 unmodified lines
24782477 if (q >= token_buf + STRING_MAX_SIZE)
24792478 goto num_too_long;
24802479 *q++ = ch;
2481− cinp();
2480+ ch = *p++;
24822481 float_frac_parse:
24832482 while (ch >= '0' && ch <= '9') {
24842483 if (q >= token_buf + STRING_MAX_SIZE)
24852484 goto num_too_long;
24862485 *q++ = ch;
2487− cinp();
2486+ ch = *p++;
24882487 }
24892488 }
24902489 if (ch == 'e' || ch == 'E') {
24912490 if (q >= token_buf + STRING_MAX_SIZE)
24922491 goto num_too_long;
24932492 *q++ = ch;
2494− cinp();
2493+ ch = *p++;
24952494 if (ch == '-' || ch == '+') {
24962495 if (q >= token_buf + STRING_MAX_SIZE)
24972496 goto num_too_long;
24982497 *q++ = ch;
2499− cinp();
2498+ ch = *p++;
25002499 }
25012500 if (ch < '0' || ch > '9')
25022501 error("exponent digits expected");
@@ -2504,18 +2503,18 @@ void parse_number(void) · 1 unmodified line
25042503 if (q >= token_buf + STRING_MAX_SIZE)
25052504 goto num_too_long;
25062505 *q++ = ch;
2507− cinp();
2506+ ch = *p++;
25082507 }
25092508 }
25102509 *q = '\0';
25112510 t = toup(ch);
25122511 errno = 0;
25132512 if (t == 'F') {
2514− cinp();
2513+ ch = *p++;
25152514 tok = TOK_CFLOAT;
25162515 tokc.f = strtof(token_buf, NULL);
25172516 } else if (t == 'L') {
2518− cinp();
2517+ ch = *p++;
25192518 tok = TOK_CLDOUBLE;
25202519 tokc.ld = strtold(token_buf, NULL);
25212520 } else {
@@ -2525,7 +2524,7 @@ void parse_number(void) · 3 unmodified lines
25252524 }
25262525 } else {
25272526 unsigned long long n, n1;
2528− int lcount;
2527+ int lcount, ucount;
25292528
25302529 /* integer number */
25312530 *q = '\0';
@@ -2552,6 +2551,7 @@ void parse_number(void) · 20 unmodified lines
25522551 n1 = n;
25532552 n = n * b + t;
25542553 /* detect overflow */
2554+ /* XXX: this test is not reliable */
25552555 if (n < n1)
25562556 error("integer constant overflow");
25572557 }
@@ -2568,11 +2568,12 @@ void parse_number(void) · 10 unmodified lines
25682568 tok = TOK_CINT;
25692569 }
25702570 lcount = 0;
2571+ ucount = 0;
25712572 for(;;) {
25722573 t = toup(ch);
25732574 if (t == 'L') {
25742575 if (lcount >= 2)
2575− error("three 'l' in integer constant");
2576+ error("three 'l's in integer constant");
25762577 lcount++;
25772578 if (lcount == 2) {
25782579 if (tok == TOK_CINT)
@@ -2580,13 +2581,16 @@ void parse_number(void) · 1 unmodified line
25802581 else if (tok == TOK_CUINT)
25812582 tok = TOK_CULLONG;
25822583 }
2583− cinp();
2584+ ch = *p++;
25842585 } else if (t == 'U') {
2586+ if (ucount >= 1)
2587+ error("two 'u's in integer constant");
2588+ ucount++;
25852589 if (tok == TOK_CINT)
25862590 tok = TOK_CUINT;
25872591 else if (tok == TOK_CLLONG)
25882592 tok = TOK_CULLONG;
2589− cinp();
2593+ ch = *p++;
25902594 } else {
25912595 break;
25922596 }
@@ -2598,7 +2602,6 @@ void parse_number(void) · 5 unmodified lines
25982602 }
25992603 }
26002604
2601−
26022605 /* return next token without macro substitution */
26032606 static inline void next_nomacro1(void)
26042607 {
@@ -2649,8 +2652,42 @@ static inline void next_nomacro1(void) · 44 unmodified lines
26492652 *q = '\0';
26502653 ts = tok_alloc(token_buf, q - token_buf);
26512654 tok = ts->tok;
2652− } else if (isnum(ch) || ch == '.') {
2653− parse_number();
2655+ } else if (isnum(ch)) {
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+ }
26542691 } else if (ch == '\'') {
26552692 tok = TOK_CCHAR;
26562693 char_const:
@@ -2824,13 +2861,6 @@ int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) · 167 unmodified lines
28242861 return str.str;
28252862 }
28262863
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−
28342864 /* handle the '##' operator */
28352865 static int *macro_twosharps(void)
28362866 {
@@ -2840,7 +2870,9 @@ static int *macro_twosharps(void) · 3 unmodified lines
28402870 const char *p1, *p2;
28412871 CValue cval;
28422872 TokenString macro_str1;
2843−
2873+ CString cstr;
2874+
2875+ cstr_new(&cstr);
28442876 tok_str_new(&macro_str1);
28452877 tok = 0;
28462878 while (1) {
@@ -2853,49 +2885,86 @@ static int *macro_twosharps(void) · 6 unmodified lines
28532885 t = *macro_ptr;
28542886 if (t) {
28552887 t = tok_get(&macro_ptr, &cval);
2856− /* XXX: not exact, but cannot do more without
2857− modifying the whole preprocessing architecture ! */
2858− /* XXX: handle arbitrary size */
2888+
2889+ /* We concatenate the two tokens if we have an
2890+ identifier or a preprocessing number */
2891+ cstr_reset(&cstr);
28592892 p1 = get_tok_str(tok, &tokc);
2860− pstrcpy(token_buf, sizeof(token_buf), p1);
2893+ cstr_cat(&cstr, p1);
28612894 p2 = get_tok_str(t, &cval);
2862− if (tok >= TOK_IDENT &&
2863− (t >= TOK_IDENT || is_tok_num(t))) {
2864− pstrcat(token_buf, sizeof(token_buf), p2);
2865− ts = tok_alloc(token_buf, strlen(token_buf));
2866− tok = ts->tok; /* modify current token */
2867− } else if (is_tok_num(tok) && is_tok_num(t)) {
2868− unsigned long long n;
2869− do_num:
2870− pstrcat(token_buf, sizeof(token_buf), p2);
2871− n = strtoull(token_buf, NULL, 10);
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;
2895+ cstr_cat(&cstr, p2);
2896+ cstr_ccat(&cstr, '\0');
2897+
2898+ if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
2899+ (t >= TOK_IDENT || t == TOK_PPNUM)) {
2900+ if (tok == TOK_PPNUM) {
2901+ /* if number, then create a number token */
2902+ /* NOTE: no need to allocate because
2903+ tok_str_add2() does it */
2904+ tokc.cstr = &cstr;
28792905 } 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 */
28812924 }
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;
28892925 } else {
2890− warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", token_buf, p2);
2891− /* cannot merge tokens: skip '##' */
2892− macro_ptr = macro_ptr1;
2893− break;
2926+ const char *str = cstr.data;
2927+ const unsigned char *q;
2928+
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+ }
28942962 }
28952963 }
28962964 }
28972965 tok_str_add2(&macro_str1, tok, &tokc);
28982966 }
2967+ cstr_free(&cstr);
28992968 tok_str_add(&macro_str1, 0);
29002969 return macro_str1.str;
29012970 }
@@ -3100,6 +3169,11 @@ void next(void) · 198 unmodified lines
31003169 goto redo;
31013170 }
31023171 }
3172+
3173+ /* convert preprocessor tokens into C tokens */
3174+ if (tok == TOK_PPNUM) {
3175+ parse_number((char *)tokc.cstr->data);
3176+ }
31033177 }
31043178 #if defined(DEBUG)
31053179 printf("token = %s\n", get_tok_str(tok, &tokc));