Annotation of gcc/cppexp.c, revision 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.