Annotation of gcc/cppexp.c, revision 1.1.1.1

1.1       root        1: /* Parse C expressions for CCCP.
                      2:    Copyright (C) 1987, 1992, 1994, 1995 Free Software Foundation.
                      3: 
                      4: This program is free software; you can redistribute it and/or modify it
                      5: under the terms of the GNU General Public License as published by the
                      6: Free Software Foundation; either version 2, or (at your option) any
                      7: later version.
                      8: 
                      9: This program is distributed in the hope that it will be useful,
                     10: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     12: GNU General Public License for more details.
                     13: 
                     14: You should have received a copy of the GNU General Public License
                     15: along with this program; if not, write to the Free Software
                     16: Foundation, 59 Temple Place - Suite 330,
                     17: Boston, MA 02111-1307, USA.
                     18: 
                     19:  In other words, you are welcome to use, share and improve this program.
                     20:  You are forbidden to forbid anyone else to use, share and improve
                     21:  what you give them.   Help stamp out software-hoarding!
                     22: 
                     23: Written by Per Bothner 1994. */
                     24: 
                     25: /* Parse a C expression from text in a string  */
                     26:    
                     27: #include "config.h"
                     28: #include "cpplib.h"
                     29: 
                     30: extern char *xmalloc PARAMS ((unsigned));
                     31: extern char *xrealloc PARAMS ((char *, unsigned));
                     32: 
                     33: #ifdef MULTIBYTE_CHARS
                     34: #include <stdlib.h>
                     35: #include <locale.h>
                     36: #endif
                     37: 
                     38: #include <stdio.h>
                     39: 
                     40: /* This is used for communicating lists of keywords with cccp.c.  */
                     41: struct arglist {
                     42:   struct arglist *next;
                     43:   U_CHAR *name;
                     44:   int length;
                     45:   int argno;
                     46: };
                     47: 
                     48: /* Define a generic NULL if one hasn't already been defined.  */
                     49: 
                     50: #ifndef NULL
                     51: #define NULL 0
                     52: #endif
                     53: 
                     54: #ifndef GENERIC_PTR
                     55: #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
                     56: #define GENERIC_PTR void *
                     57: #else
                     58: #define GENERIC_PTR char *
                     59: #endif
                     60: #endif
                     61: 
                     62: #ifndef NULL_PTR
                     63: #define NULL_PTR ((GENERIC_PTR)0)
                     64: #endif
                     65: 
                     66: extern char *xmalloc ();
                     67: 
                     68: #ifndef CHAR_TYPE_SIZE
                     69: #define CHAR_TYPE_SIZE BITS_PER_UNIT
                     70: #endif
                     71: 
                     72: #ifndef INT_TYPE_SIZE
                     73: #define INT_TYPE_SIZE BITS_PER_WORD
                     74: #endif
                     75: 
                     76: #ifndef LONG_TYPE_SIZE
                     77: #define LONG_TYPE_SIZE BITS_PER_WORD
                     78: #endif
                     79: 
                     80: #ifndef WCHAR_TYPE_SIZE
                     81: #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
                     82: #endif
                     83: 
                     84: #ifndef MAX_CHAR_TYPE_SIZE
                     85: #define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE
                     86: #endif
                     87: 
                     88: #ifndef MAX_INT_TYPE_SIZE
                     89: #define MAX_INT_TYPE_SIZE INT_TYPE_SIZE
                     90: #endif
                     91: 
                     92: #ifndef MAX_LONG_TYPE_SIZE
                     93: #define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE
                     94: #endif
                     95: 
                     96: #ifndef MAX_WCHAR_TYPE_SIZE
                     97: #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
                     98: #endif
                     99: 
                    100: /* Yield nonzero if adding two numbers with A's and B's signs can yield a
                    101:    number with SUM's sign, where A, B, and SUM are all C integers.  */
                    102: #define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0)
                    103: 
                    104: static void integer_overflow ();
                    105: static long left_shift ();
                    106: static long right_shift ();
                    107: 
                    108: #define ERROR 299
                    109: #define OROR 300
                    110: #define ANDAND 301
                    111: #define EQUAL 302
                    112: #define NOTEQUAL 303
                    113: #define LEQ 304
                    114: #define GEQ 305
                    115: #define LSH 306
                    116: #define RSH 307
                    117: #define NAME 308
                    118: #define INT 309
                    119: #define CHAR 310
                    120: 
                    121: #define LEFT_OPERAND_REQUIRED 1
                    122: #define RIGHT_OPERAND_REQUIRED 2
                    123: #define HAVE_VALUE 4
                    124: /*#define UNSIGNEDP 8*/
                    125: 
                    126: #ifndef HOST_BITS_PER_WIDE_INT
                    127: 
                    128: #if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
                    129: #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
                    130: #define HOST_WIDE_INT long
                    131: #else
                    132: #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
                    133: #define HOST_WIDE_INT int
                    134: #endif
                    135: 
                    136: #endif
                    137: 
                    138: struct operation {
                    139:     short op;
                    140:     char rprio; /* Priority of op (relative to it right operand). */
                    141:     char flags;
                    142:     char unsignedp;    /* true if value should be treated as unsigned */
                    143:     HOST_WIDE_INT value;        /* The value logically "right" of op. */
                    144: };
                    145: 
                    146: /* Take care of parsing a number (anything that starts with a digit).
                    147:    LEN is the number of characters in it.  */
                    148: 
                    149: /* maybe needs to actually deal with floating point numbers */
                    150: 
                    151: struct operation
                    152: parse_number (pfile, start, olen)
                    153:      cpp_reader *pfile;
                    154:      char *start;
                    155:      int olen;
                    156: {
                    157:   struct operation op;
                    158:   register char *p = start;
                    159:   register int c;
                    160:   register unsigned long n = 0, nd, ULONG_MAX_over_base;
                    161:   register int base = 10;
                    162:   register int len = olen;
                    163:   register int overflow = 0;
                    164:   register int digit, largest_digit = 0;
                    165:   int spec_long = 0;
                    166: 
                    167:   op.unsignedp = 0;
                    168: 
                    169:   for (c = 0; c < len; c++)
                    170:     if (p[c] == '.') {
                    171:       /* It's a float since it contains a point.  */
                    172:       cpp_error (pfile,
                    173:                 "floating point numbers not allowed in #if expressions");
                    174:       op.op = ERROR;
                    175:       return op;
                    176:     }
                    177: 
                    178:   if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) {
                    179:     p += 2;
                    180:     base = 16;
                    181:     len -= 2;
                    182:   }
                    183:   else if (*p == '0')
                    184:     base = 8;
                    185: 
                    186:   /* Some buggy compilers (e.g. MPW C) seem to need both casts. */
                    187:   ULONG_MAX_over_base = ((unsigned long) -1) / ((unsigned long) base);
                    188: 
                    189:   for (; len > 0; len--) {
                    190:     c = *p++;
                    191: 
                    192:     if (c >= '0' && c <= '9')
                    193:       digit = c - '0';
                    194:     else if (base == 16 && c >= 'a' && c <= 'f')
                    195:       digit = c - 'a' + 10;
                    196:     else if (base == 16 && c >= 'A' && c <= 'F')
                    197:       digit = c - 'A' + 10;
                    198:     else {
                    199:       /* `l' means long, and `u' means unsigned.  */
                    200:       while (1) {
                    201:        if (c == 'l' || c == 'L')
                    202:          {
                    203:            if (spec_long)
                    204:              cpp_error (pfile, "two `l's in integer constant");
                    205:            spec_long = 1;
                    206:          }
                    207:        else if (c == 'u' || c == 'U')
                    208:          {
                    209:            if (op.unsignedp)
                    210:              cpp_error (pfile, "two `u's in integer constant");
                    211:            op.unsignedp = 1;
                    212:          }
                    213:        else
                    214:          break;
                    215: 
                    216:        if (--len == 0)
                    217:          break;
                    218:        c = *p++;
                    219:       }
                    220:       /* Don't look for any more digits after the suffixes.  */
                    221:       break;
                    222:     }
                    223:     if (largest_digit < digit)
                    224:       largest_digit = digit;
                    225:     nd = n * base + digit;
                    226:     overflow |= ULONG_MAX_over_base < n | nd < n;
                    227:     n = nd;
                    228:   }
                    229: 
                    230:   if (len != 0)
                    231:     {
                    232:       cpp_error (pfile, "Invalid number in #if expression");
                    233:       op.op = ERROR;
                    234:       return op;
                    235:     }
                    236: 
                    237:   if (base <= largest_digit)
                    238:     cpp_warning (pfile, "integer constant contains digits beyond the radix");
                    239: 
                    240:   if (overflow)
                    241:     cpp_warning (pfile, "integer constant out of range");
                    242: 
                    243:   /* If too big to be signed, consider it unsigned.  */
                    244:   if ((long) n < 0 && ! op.unsignedp)
                    245:     {
                    246:       if (base == 10)
                    247:        cpp_warning (pfile, "integer constant is so large that it is unsigned");
                    248:       op.unsignedp = 1;
                    249:     }
                    250: 
                    251:   op.value = n;
                    252:   op.op = INT;
                    253:   return op;
                    254: }
                    255: 
                    256: struct token {
                    257:   char *operator;
                    258:   int token;
                    259: };
                    260: 
                    261: static struct token tokentab2[] = {
                    262:   {"&&", ANDAND},
                    263:   {"||", OROR},
                    264:   {"<<", LSH},
                    265:   {">>", RSH},
                    266:   {"==", EQUAL},
                    267:   {"!=", NOTEQUAL},
                    268:   {"<=", LEQ},
                    269:   {">=", GEQ},
                    270:   {"++", ERROR},
                    271:   {"--", ERROR},
                    272:   {NULL, ERROR}
                    273: };
                    274: 
                    275: /* Read one token. */
                    276: 
                    277: struct operation
                    278: cpp_lex (pfile)
                    279: cpp_reader *pfile;
                    280: {
                    281:   register int c;
                    282:   register int namelen;
                    283:   register struct token *toktab;
                    284:   enum cpp_token token;
                    285:   struct operation op;
                    286:   U_CHAR *tok_start, *tok_end;
                    287:   int old_written;
                    288: 
                    289:  retry:
                    290: 
                    291:   old_written = CPP_WRITTEN (pfile);
                    292:   cpp_skip_hspace (pfile);
                    293:   c = CPP_BUF_PEEK (CPP_BUFFER (pfile));
                    294:   if (c == '#')
                    295:     return parse_number (pfile,
                    296:                         cpp_read_check_assertion (pfile) ? "1" : "0", 1);
                    297: 
                    298:   if (c == '\n')
                    299:     {
                    300:       op.op = 0;
                    301:       return op;
                    302:     }
                    303: 
                    304:   token = cpp_get_token (pfile);
                    305:   tok_start = pfile->token_buffer + old_written;
                    306:   tok_end = CPP_PWRITTEN (pfile);
                    307:   pfile->limit = tok_start;
                    308:   switch (token)
                    309:   {
                    310:     case CPP_EOF: /* Should not happen ... */
                    311:       op.op = 0;
                    312:       return op;
                    313:     case CPP_VSPACE:
                    314:     case CPP_POP:
                    315:       if (CPP_BUFFER (pfile)->fname != NULL)
                    316:        {
                    317:          op.op = 0;
                    318:          return op;
                    319:        }
                    320:       goto retry;
                    321:     case CPP_HSPACE:   case CPP_COMMENT: 
                    322:       goto retry;
                    323:     case CPP_NUMBER:
                    324:       return parse_number (pfile, tok_start, tok_end - tok_start);
                    325:     case CPP_STRING:
                    326:       cpp_error (pfile, "string constants not allowed in #if expressions");
                    327:       op.op = ERROR;
                    328:       return op;
                    329:     case CPP_CHAR:
                    330:       /* This code for reading a character constant
                    331:         handles multicharacter constants and wide characters.
                    332:         It is mostly copied from c-lex.c.  */
                    333:       {
                    334:         register int result = 0;
                    335:        register num_chars = 0;
                    336:        unsigned width = MAX_CHAR_TYPE_SIZE;
                    337:        int wide_flag = 0;
                    338:        int max_chars;
                    339:        U_CHAR *ptr = tok_start;
                    340: #ifdef MULTIBYTE_CHARS
                    341:        char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + MB_CUR_MAX];
                    342: #else
                    343:        char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + 1];
                    344: #endif
                    345: 
                    346:        if (*ptr == 'L')
                    347:          {
                    348:            ptr++;
                    349:            wide_flag = 1;
                    350:            width = MAX_WCHAR_TYPE_SIZE;
                    351: #ifdef MULTIBYTE_CHARS
                    352:            max_chars = MB_CUR_MAX;
                    353: #else
                    354:            max_chars = 1;
                    355: #endif
                    356:          }
                    357:        else
                    358:            max_chars = MAX_LONG_TYPE_SIZE / width;
                    359: 
                    360:        ++ptr;
                    361:        while (ptr < tok_end && ((c = *ptr++) != '\''))
                    362:          {
                    363:            if (c == '\\')
                    364:              {
                    365:                c = cpp_parse_escape (pfile, &ptr);
                    366:                if (width < HOST_BITS_PER_INT
                    367:                  && (unsigned) c >= (1 << width))
                    368:                    cpp_pedwarn (pfile,
                    369:                                 "escape sequence out of range for character");
                    370:              }
                    371: 
                    372:            num_chars++;
                    373: 
                    374:            /* Merge character into result; ignore excess chars.  */
                    375:            if (num_chars < max_chars + 1)
                    376:              {
                    377:                if (width < HOST_BITS_PER_INT)
                    378:                  result = (result << width) | (c & ((1 << width) - 1));
                    379:                else
                    380:                  result = c;
                    381:                token_buffer[num_chars - 1] = c;
                    382:              }
                    383:          }
                    384: 
                    385:        token_buffer[num_chars] = 0;
                    386: 
                    387:        if (c != '\'')
                    388:          cpp_error (pfile, "malformatted character constant");
                    389:        else if (num_chars == 0)
                    390:          cpp_error (pfile, "empty character constant");
                    391:        else if (num_chars > max_chars)
                    392:          {
                    393:            num_chars = max_chars;
                    394:            cpp_error (pfile, "character constant too long");
                    395:          }
                    396:        else if (num_chars != 1 && ! CPP_TRADITIONAL (pfile))
                    397:          cpp_warning (pfile, "multi-character character constant");
                    398: 
                    399:        /* If char type is signed, sign-extend the constant.  */
                    400:        if (! wide_flag)
                    401:          {
                    402:            int num_bits = num_chars * width;
                    403: 
                    404:            if (cpp_lookup (pfile, "__CHAR_UNSIGNED__",
                    405:                            sizeof ("__CHAR_UNSIGNED__")-1, -1)
                    406:                || ((result >> (num_bits - 1)) & 1) == 0)
                    407:                op.value
                    408:                    = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
                    409:            else
                    410:                op.value
                    411:                    = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
                    412:          }
                    413:        else
                    414:          {
                    415: #ifdef MULTIBYTE_CHARS
                    416:            /* Set the initial shift state and convert the next sequence.  */
                    417:              result = 0;
                    418:              /* In all locales L'\0' is zero and mbtowc will return zero,
                    419:                 so don't use it.  */
                    420:              if (num_chars > 1
                    421:                  || (num_chars == 1 && token_buffer[0] != '\0'))
                    422:                {
                    423:                  wchar_t wc;
                    424:                  (void) mbtowc (NULL_PTR, NULL_PTR, 0);
                    425:                  if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
                    426:                    result = wc;
                    427:                  else
                    428:                    cpp_warning (pfile,"Ignoring invalid multibyte character");
                    429:                }
                    430: #endif
                    431:              op.value = result;
                    432:            }
                    433:         }
                    434: 
                    435:       /* This is always a signed type.  */
                    436:       op.unsignedp = 0;
                    437:       op.op = CHAR;
                    438:     
                    439:       return op;
                    440: 
                    441:     case CPP_NAME:
                    442:       return parse_number (pfile, "0", 0);
                    443: 
                    444:     case CPP_OTHER:
                    445:       /* See if it is a special token of length 2.  */
                    446:       if (tok_start + 2 == tok_end)
                    447:         {
                    448:          for (toktab = tokentab2; toktab->operator != NULL; toktab++)
                    449:            if (tok_start[0] == toktab->operator[0]
                    450:                && tok_start[1] == toktab->operator[1])
                    451:                break;
                    452:          if (toktab->token == ERROR)
                    453:            {
                    454:              char *buf = (char *) alloca (40);
                    455:              sprintf (buf, "`%s' not allowed in operand of `#if'", tok_start);
                    456:              cpp_error (pfile, buf);
                    457:            }
                    458:          op.op = toktab->token; 
                    459:          return op;
                    460:        }
                    461:       /* fall through */
                    462:     default:
                    463:       op.op = *tok_start;
                    464:       return op;
                    465:   }
                    466: }
                    467: 
                    468: 
                    469: /* Parse a C escape sequence.  STRING_PTR points to a variable
                    470:    containing a pointer to the string to parse.  That pointer
                    471:    is updated past the characters we use.  The value of the
                    472:    escape sequence is returned.
                    473: 
                    474:    A negative value means the sequence \ newline was seen,
                    475:    which is supposed to be equivalent to nothing at all.
                    476: 
                    477:    If \ is followed by a null character, we return a negative
                    478:    value and leave the string pointer pointing at the null character.
                    479: 
                    480:    If \ is followed by 000, we return 0 and leave the string pointer
                    481:    after the zeros.  A value of 0 does not mean end of string.  */
                    482: 
                    483: int
                    484: cpp_parse_escape (pfile, string_ptr)
                    485:      cpp_reader *pfile;
                    486:      char **string_ptr;
                    487: {
                    488:   register int c = *(*string_ptr)++;
                    489:   switch (c)
                    490:     {
                    491:     case 'a':
                    492:       return TARGET_BELL;
                    493:     case 'b':
                    494:       return TARGET_BS;
                    495:     case 'e':
                    496:     case 'E':
                    497:       if (CPP_PEDANTIC (pfile))
                    498:        cpp_pedwarn (pfile, "non-ANSI-standard escape sequence, `\\%c'", c);
                    499:       return 033;
                    500:     case 'f':
                    501:       return TARGET_FF;
                    502:     case 'n':
                    503:       return TARGET_NEWLINE;
                    504:     case 'r':
                    505:       return TARGET_CR;
                    506:     case 't':
                    507:       return TARGET_TAB;
                    508:     case 'v':
                    509:       return TARGET_VT;
                    510:     case '\n':
                    511:       return -2;
                    512:     case 0:
                    513:       (*string_ptr)--;
                    514:       return 0;
                    515:       
                    516:     case '0':
                    517:     case '1':
                    518:     case '2':
                    519:     case '3':
                    520:     case '4':
                    521:     case '5':
                    522:     case '6':
                    523:     case '7':
                    524:       {
                    525:        register int i = c - '0';
                    526:        register int count = 0;
                    527:        while (++count < 3)
                    528:          {
                    529:            c = *(*string_ptr)++;
                    530:            if (c >= '0' && c <= '7')
                    531:              i = (i << 3) + c - '0';
                    532:            else
                    533:              {
                    534:                (*string_ptr)--;
                    535:                break;
                    536:              }
                    537:          }
                    538:        if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
                    539:          {
                    540:            i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
                    541:            cpp_warning (pfile,
                    542:                          "octal character constant does not fit in a byte");
                    543:          }
                    544:        return i;
                    545:       }
                    546:     case 'x':
                    547:       {
                    548:        register unsigned i = 0, overflow = 0, digits_found = 0, digit;
                    549:        for (;;)
                    550:          {
                    551:            c = *(*string_ptr)++;
                    552:            if (c >= '0' && c <= '9')
                    553:              digit = c - '0';
                    554:            else if (c >= 'a' && c <= 'f')
                    555:              digit = c - 'a' + 10;
                    556:            else if (c >= 'A' && c <= 'F')
                    557:              digit = c - 'A' + 10;
                    558:            else
                    559:              {
                    560:                (*string_ptr)--;
                    561:                break;
                    562:              }
                    563:            overflow |= i ^ (i << 4 >> 4);
                    564:            i = (i << 4) + digit;
                    565:            digits_found = 1;
                    566:          }
                    567:        if (!digits_found)
                    568:          cpp_error (pfile, "\\x used with no following hex digits");
                    569:        if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1)))
                    570:          {
                    571:            i &= (1 << BITS_PER_UNIT) - 1;
                    572:            cpp_warning (pfile,
                    573:                         "hex character constant does not fit in a byte");
                    574:          }
                    575:        return i;
                    576:       }
                    577:     default:
                    578:       return c;
                    579:     }
                    580: }
                    581: 
                    582: static void
                    583: integer_overflow (pfile)
                    584:      cpp_reader *pfile;
                    585: {
                    586:   if (CPP_PEDANTIC (pfile))
                    587:     cpp_pedwarn (pfile, "integer overflow in preprocessor expression");
                    588: }
                    589: 
                    590: static long
                    591: left_shift (pfile, a, unsignedp, b)
                    592:      cpp_reader *pfile;
                    593:      long a;
                    594:      int unsignedp;
                    595:      unsigned long b;
                    596: {
                    597:   if (b >= HOST_BITS_PER_LONG)
                    598:     {
                    599:       if (! unsignedp && a != 0)
                    600:        integer_overflow (pfile);
                    601:       return 0;
                    602:     }
                    603:   else if (unsignedp)
                    604:     return (unsigned long) a << b;
                    605:   else
                    606:     {
                    607:       long l = a << b;
                    608:       if (l >> b != a)
                    609:        integer_overflow (pfile);
                    610:       return l;
                    611:     }
                    612: }
                    613: 
                    614: static long
                    615: right_shift (pfile, a, unsignedp, b)
                    616:      cpp_reader *pfile;
                    617:      long a;
                    618:      int unsignedp;
                    619:      unsigned long b;
                    620: {
                    621:   if (b >= HOST_BITS_PER_LONG)
                    622:     return unsignedp ? 0 : a >> (HOST_BITS_PER_LONG - 1);
                    623:   else if (unsignedp)
                    624:     return (unsigned long) a >> b;
                    625:   else
                    626:     return a >> b;
                    627: }
                    628: 
                    629: /* These priorities are all even, so we can handle associatively. */
                    630: #define PAREN_INNER_PRIO 0
                    631: #define COMMA_PRIO 4
                    632: #define COND_PRIO (COMMA_PRIO+2)
                    633: #define OROR_PRIO (COND_PRIO+2)
                    634: #define ANDAND_PRIO (OROR_PRIO+2)
                    635: #define OR_PRIO (ANDAND_PRIO+2)
                    636: #define XOR_PRIO (OR_PRIO+2)
                    637: #define AND_PRIO (XOR_PRIO+2)
                    638: #define EQUAL_PRIO (AND_PRIO+2)
                    639: #define LESS_PRIO (EQUAL_PRIO+2)
                    640: #define SHIFT_PRIO (LESS_PRIO+2)
                    641: #define PLUS_PRIO (SHIFT_PRIO+2)
                    642: #define MUL_PRIO (PLUS_PRIO+2)
                    643: #define UNARY_PRIO (MUL_PRIO+2)
                    644: #define PAREN_OUTER_PRIO (UNARY_PRIO+2)
                    645: 
                    646: #define COMPARE(OP) \
                    647:   top->unsignedp = 0;\
                    648:   top->value = (unsigned1 || unsigned2) ? (unsigned long) v1 OP v2 : (v1 OP v2)
                    649: 
                    650: /* Parse and evaluate a C expression, reading from PFILE.
                    651:    Returns the value of the expression.  */
                    652: 
                    653: HOST_WIDE_INT
                    654: cpp_parse_expr (pfile)
                    655:      cpp_reader *pfile;
                    656: {
                    657:   /* The implementation is an operator precedence parser,
                    658:      i.e. a bottom-up parser, using a stack for not-yet-reduced tokens.
                    659: 
                    660:      The stack base is 'stack', and the current stack pointer is 'top'.
                    661:      There is a stack element for each operator (only),
                    662:      and the most recently pushed operator is 'top->op'.
                    663:      An operand (value) is stored in the 'value' field of the stack
                    664:      element of the operator that precedes it.
                    665:      In that case the 'flags' field has the HAVE_VALUE flag set.  */
                    666: 
                    667: #define INIT_STACK_SIZE 20
                    668:   struct operation init_stack[INIT_STACK_SIZE];
                    669:   struct operation *stack = init_stack;
                    670:   struct operation *limit = stack + INIT_STACK_SIZE;
                    671:   register struct operation *top = stack;
                    672:   int lprio, rprio;
                    673: 
                    674:   top->rprio = 0;
                    675:   top->flags = 0;
                    676:   for (;;)
                    677:     {
                    678:       struct operation op;
                    679:       char flags = 0;
                    680: 
                    681:       /* Read a token */
                    682:       op =  cpp_lex (pfile);
                    683: 
                    684:       /* See if the token is an operand, in which case go to set_value.
                    685:         If the token is an operator, figure out its left and right
                    686:         priorities, and then goto maybe_reduce. */
                    687: 
                    688:       switch (op.op)
                    689:        {
                    690:        case NAME:
                    691:          top->value = 0, top->unsignedp = 0;
                    692:          goto set_value;
                    693:        case INT:  case CHAR:
                    694:          top->value = op.value;
                    695:          top->unsignedp = op.unsignedp;
                    696:          goto set_value;
                    697:        case 0:
                    698:          lprio = 0;  goto maybe_reduce;
                    699:        case '+':  case '-':
                    700:          /* Is this correct if unary ? FIXME */
                    701:          flags = RIGHT_OPERAND_REQUIRED;
                    702:          lprio = PLUS_PRIO;  rprio = lprio + 1;  goto maybe_reduce;
                    703:        case '!':  case '~':
                    704:          flags = RIGHT_OPERAND_REQUIRED;
                    705:          rprio = UNARY_PRIO;  lprio = rprio + 1;  goto maybe_reduce;
                    706:        case '*':  case '/':  case '%':
                    707:          lprio = MUL_PRIO;  goto binop;
                    708:        case '<':  case '>':  case LEQ:  case GEQ:
                    709:          lprio = LESS_PRIO;  goto binop;
                    710:        case EQUAL:  case NOTEQUAL:
                    711:          lprio = EQUAL_PRIO;  goto binop;
                    712:        case LSH:  case RSH:
                    713:          lprio = SHIFT_PRIO;  goto binop;
                    714:        case '&':  lprio = AND_PRIO;  goto binop;
                    715:        case '^':  lprio = XOR_PRIO;  goto binop;
                    716:        case '|':  lprio = OR_PRIO;  goto binop;
                    717:        case ANDAND:  lprio = ANDAND_PRIO;  goto binop;
                    718:        case OROR:  lprio = OROR_PRIO;  goto binop;
                    719:        case ',':
                    720:          lprio = COMMA_PRIO;  goto binop;
                    721:        case '(':
                    722:          lprio = PAREN_OUTER_PRIO;  rprio = PAREN_INNER_PRIO;
                    723:          goto maybe_reduce;
                    724:        case ')':
                    725:          lprio = PAREN_INNER_PRIO;  rprio = PAREN_OUTER_PRIO;
                    726:          goto maybe_reduce;
                    727:         case ':':
                    728:          lprio = COND_PRIO;  rprio = COND_PRIO;
                    729:          goto maybe_reduce;
                    730:         case '?':
                    731:          lprio = COND_PRIO + 1;  rprio = COND_PRIO;
                    732:          goto maybe_reduce;
                    733:        binop:
                    734:          flags = LEFT_OPERAND_REQUIRED|RIGHT_OPERAND_REQUIRED;
                    735:          rprio = lprio + 1;
                    736:          goto maybe_reduce;
                    737:        default:
                    738:          cpp_error (pfile, "invalid character in #if");
                    739:          goto syntax_error;
                    740:        }
                    741: 
                    742:     set_value:
                    743:       /* Push a value onto the stack. */
                    744:       if (top->flags & HAVE_VALUE)
                    745:        {
                    746:          cpp_error (pfile, "syntax error in #if");
                    747:          goto syntax_error;
                    748:        }
                    749:       top->flags |= HAVE_VALUE;
                    750:       continue;
                    751: 
                    752:     maybe_reduce:
                    753:       /* Push an operator, and check if we can reduce now. */
                    754:       while (top->rprio > lprio)
                    755:        {
                    756:          long v1 = top[-1].value, v2 = top[0].value;
                    757:          int unsigned1 = top[-1].unsignedp, unsigned2 = top[0].unsignedp;
                    758:          top--;
                    759:          if ((top[1].flags & LEFT_OPERAND_REQUIRED)
                    760:              && ! (top[0].flags & HAVE_VALUE))
                    761:            {
                    762:              cpp_error (pfile, "syntax error - missing left operand");
                    763:              goto syntax_error;
                    764:            }
                    765:          if ((top[1].flags & RIGHT_OPERAND_REQUIRED)
                    766:              && ! (top[1].flags & HAVE_VALUE))
                    767:            {
                    768:              cpp_error (pfile, "syntax error - missing right operand");
                    769:              goto syntax_error;
                    770:            }
                    771:          /* top[0].value = (top[1].op)(v1, v2);*/
                    772:          switch (top[1].op)
                    773:            {
                    774:            case '+':
                    775:              if (!(top->flags & HAVE_VALUE))
                    776:                { /* Unary '+' */
                    777:                  top->value = v2;
                    778:                  top->unsignedp = unsigned2;
                    779:                  top->flags |= HAVE_VALUE;
                    780:                }
                    781:              else
                    782:                {
                    783:                  top->value = v1 + v2;
                    784:                  top->unsignedp = unsigned1 || unsigned2;
                    785:                  if (! top->unsignedp
                    786:                      && ! possible_sum_sign (v1, v2, top->value))
                    787:                    integer_overflow (pfile);
                    788:                }
                    789:              break;
                    790:            case '-':
                    791:              if (!(top->flags & HAVE_VALUE))
                    792:                { /* Unary '-' */
                    793:                  top->value = - v2;
                    794:                  if ((top->value & v2) < 0 && ! unsigned2)
                    795:                    integer_overflow (pfile);
                    796:                  top->unsignedp = unsigned2;
                    797:                  top->flags |= HAVE_VALUE;
                    798:                }
                    799:              else
                    800:                { /* Binary '-' */
                    801:                  top->value = v1 - v2;
                    802:                  top->unsignedp = unsigned1 || unsigned2;
                    803:                  if (! top->unsignedp
                    804:                      && ! possible_sum_sign (top->value, v2, v1))
                    805:                    integer_overflow (pfile);
                    806:                }
                    807:              break;
                    808:            case '*':
                    809:              top->unsignedp = unsigned1 || unsigned2;
                    810:              if (top->unsignedp)
                    811:                top->value = (unsigned long) v1 * v2;
                    812:              else
                    813:                {
                    814:                  top->value = v1 * v2;
                    815:                  if (v1
                    816:                      && (top->value / v1 != v2
                    817:                          || (top->value & v1 & v2) < 0))
                    818:                    integer_overflow (pfile);
                    819:                }
                    820:              break;
                    821:            case '/':
                    822:              if (v2 == 0)
                    823:                {
                    824:                  cpp_error (pfile, "division by zero in #if");
                    825:                  v2 = 1;
                    826:                }
                    827:              top->unsignedp = unsigned1 || unsigned2;
                    828:              if (top->unsignedp)
                    829:                top->value = (unsigned long) v1 / v2;
                    830:              else
                    831:                {
                    832:                  top->value = v1 / v2;
                    833:                  if ((top->value & v1 & v2) < 0)
                    834:                    integer_overflow (pfile);
                    835:                }
                    836:              break;
                    837:            case '%':
                    838:              if (v2 == 0)
                    839:                {
                    840:                  cpp_error (pfile, "division by zero in #if");
                    841:                  v2 = 1;
                    842:                }
                    843:              top->unsignedp = unsigned1 || unsigned2;
                    844:              if (top->unsignedp)
                    845:                top->value = (unsigned long) v1 % v2;
                    846:              else
                    847:                top->value = v1 % v2;
                    848:              break;
                    849:            case '!':
                    850:              if (top->flags & HAVE_VALUE)
                    851:                {
                    852:                  cpp_error (pfile, "syntax error");
                    853:                  goto syntax_error;
                    854:                }
                    855:              top->value = ! v2;
                    856:              top->unsignedp = 0;
                    857:              top->flags |= HAVE_VALUE;
                    858:              break;
                    859:            case '~':
                    860:              if (top->flags & HAVE_VALUE)
                    861:                {
                    862:                  cpp_error (pfile, "syntax error");
                    863:                  goto syntax_error;
                    864:                }
                    865:              top->value = ~ v2;
                    866:              top->unsignedp = unsigned2;
                    867:              top->flags |= HAVE_VALUE;
                    868:              break;
                    869:            case '<':  COMPARE(<);  break;
                    870:            case '>':  COMPARE(>);  break;
                    871:            case LEQ:  COMPARE(<=); break;
                    872:            case GEQ:  COMPARE(>=); break;
                    873:            case EQUAL:
                    874:              top->value = (v1 == v2);
                    875:              top->unsignedp = 0;
                    876:              break;
                    877:            case NOTEQUAL:
                    878:              top->value = (v1 != v2);
                    879:              top->unsignedp = 0;
                    880:              break;
                    881:            case LSH:
                    882:              top->unsignedp = unsigned1;
                    883:              if (v2 < 0 && ! unsigned2)
                    884:                top->value = right_shift (pfile, v1, unsigned1, -v2);
                    885:              else
                    886:                top->value = left_shift (pfile, v1, unsigned1, v2);
                    887:              break;
                    888:            case RSH:
                    889:              top->unsignedp = unsigned1;
                    890:              if (v2 < 0 && ! unsigned2)
                    891:                top->value = left_shift (pfile, v1, unsigned1, -v2);
                    892:              else
                    893:                top->value = right_shift (pfile, v1, unsigned1, v2);
                    894:              break;
                    895: #define LOGICAL(OP) \
                    896:              top->value = v1 OP v2;\
                    897:              top->unsignedp = unsigned1 || unsigned2;
                    898:            case '&':  LOGICAL(&); break;
                    899:            case '^':  LOGICAL(^);  break;
                    900:            case '|':  LOGICAL(|);  break;
                    901:            case ANDAND:
                    902:              top->value = v1 && v2;  top->unsignedp = 0;  break;
                    903:            case OROR:
                    904:              top->value = v1 || v2;  top->unsignedp = 0;  break;
                    905:            case ',':
                    906:              if (CPP_PEDANTIC (pfile))
                    907:                cpp_pedwarn (pfile, "comma operator in operand of `#if'");
                    908:              top->value = v2;
                    909:              top->unsignedp = unsigned2;
                    910:              break;
                    911:            case '(':  case '?':
                    912:              cpp_error (pfile, "syntax error in #if");
                    913:              goto syntax_error;
                    914:            case ':':
                    915:              if (top[0].op != '?')
                    916:                {
                    917:                  cpp_error (pfile,
                    918:                             "syntax error ':' without preceding '?'");
                    919:                  goto syntax_error;
                    920:                }
                    921:              else if (! (top[1].flags & HAVE_VALUE)
                    922:                       || !(top[-1].flags & HAVE_VALUE)
                    923:                       || !(top[0].flags & HAVE_VALUE))
                    924:                {
                    925:                  cpp_error (pfile, "bad syntax for ?: operator");
                    926:                  goto syntax_error;
                    927:                }
                    928:              else
                    929:                {
                    930:                  top--;
                    931:                  top->value = top->value ? v1 : v2;
                    932:                  top->unsignedp = unsigned1 || unsigned2;
                    933:                }
                    934:              break;
                    935:            case ')':
                    936:              if ((top[1].flags & HAVE_VALUE)
                    937:                  || ! (top[0].flags & HAVE_VALUE)
                    938:                  || top[0].op != '('
                    939:                  || (top[-1].flags & HAVE_VALUE))
                    940:                {
                    941:                  cpp_error (pfile, "mismatched parentheses in #if");
                    942:                  goto syntax_error;
                    943:                }
                    944:              else
                    945:                {
                    946:                  top--;
                    947:                  top->value = v1;
                    948:                  top->unsignedp = unsigned1;
                    949:                  top->flags |= HAVE_VALUE;
                    950:                }
                    951:              break;
                    952:            default:
                    953:              fprintf (stderr,
                    954:                       top[1].op >= ' ' && top[1].op <= '~'
                    955:                       ? "unimplemented operator '%c'\n"
                    956:                       : "unimplemented operator '\\%03o'\n",
                    957:                       top[1].op);
                    958:            }
                    959:        }
                    960:       if (op.op == 0)
                    961:        {
                    962:          if (top != stack)
                    963:            cpp_error (pfile, "internal error in #if expression");
                    964:          if (stack != init_stack)
                    965:            free (stack);
                    966:          return top->value;
                    967:        }
                    968:       top++;
                    969:       
                    970:       /* Check for and handle stack overflow. */
                    971:       if (top == limit)
                    972:        {
                    973:          struct operation *new_stack;
                    974:          int old_size = (char*)limit - (char*)stack;
                    975:          int new_size = 2 * old_size;
                    976:          if (stack != init_stack)
                    977:            new_stack = (struct operation*) xrealloc (stack, new_size);
                    978:          else
                    979:            {
                    980:              new_stack = (struct operation*) xmalloc (new_size);
                    981:              bcopy ((char *) stack, (char *) new_stack, old_size);
                    982:            }
                    983:          stack = new_stack;
                    984:          top = (struct operation*)((char*) new_stack + old_size);
                    985:          limit = (struct operation*)((char*) new_stack + new_size);
                    986:        }
                    987:       
                    988:       top->flags = flags;
                    989:       top->rprio = rprio;
                    990:       top->op = op.op;
                    991:     }
                    992:  syntax_error:
                    993:   if (stack != init_stack)
                    994:     free (stack);
                    995:   skip_rest_of_line (pfile);
                    996:   return 0;
                    997: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.