Annotation of GNUtools/cc/cexp.y, revision 1.1

1.1     ! root        1: /* Parse C expressions for CCCP.
        !             2:    Copyright (C) 1987, 1992 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, 675 Mass Ave, Cambridge, MA 02139, USA.
        !            17: 
        !            18:  In other words, you are welcome to use, share and improve this program.
        !            19:  You are forbidden to forbid anyone else to use, share and improve
        !            20:  what you give them.   Help stamp out software-hoarding!
        !            21: 
        !            22:  Adapted from expread.y of GDB by Paul Rubin, July 1986.  */
        !            23: 
        !            24: /* Parse a C expression from text in a string  */
        !            25:    
        !            26: %{
        !            27: #include "config.h"
        !            28: #include <setjmp.h>
        !            29: /* #define YYDEBUG 1 */
        !            30: 
        !            31: #ifdef MULTIBYTE_CHARS
        !            32: #include <stdlib.h>
        !            33: #include <locale.h>
        !            34: #endif
        !            35: 
        !            36: #include <stdio.h>
        !            37: 
        !            38: typedef unsigned char U_CHAR;
        !            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: int yylex ();
        !            67: void yyerror ();
        !            68: int expression_value;
        !            69: 
        !            70: static jmp_buf parse_return_error;
        !            71: 
        !            72: /* Nonzero means count most punctuation as part of a name.  */
        !            73: static int keyword_parsing = 0;
        !            74: 
        !            75: /* some external tables of character types */
        !            76: extern unsigned char is_idstart[], is_idchar[], is_hor_space[];
        !            77: 
        !            78: extern char *xmalloc ();
        !            79: 
        !            80: /* Flag for -pedantic.  */
        !            81: extern int pedantic;
        !            82: 
        !            83: /* Flag for -traditional.  */
        !            84: extern int traditional;
        !            85: 
        !            86: #ifndef CHAR_TYPE_SIZE
        !            87: #define CHAR_TYPE_SIZE BITS_PER_UNIT
        !            88: #endif
        !            89: 
        !            90: #ifndef INT_TYPE_SIZE
        !            91: #define INT_TYPE_SIZE BITS_PER_WORD
        !            92: #endif
        !            93: 
        !            94: #ifndef LONG_TYPE_SIZE
        !            95: #define LONG_TYPE_SIZE BITS_PER_WORD
        !            96: #endif
        !            97: 
        !            98: #ifndef WCHAR_TYPE_SIZE
        !            99: #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
        !           100: #endif
        !           101: 
        !           102: #ifndef MAX_CHAR_TYPE_SIZE
        !           103: #define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE
        !           104: #endif
        !           105: 
        !           106: #ifndef MAX_INT_TYPE_SIZE
        !           107: #define MAX_INT_TYPE_SIZE INT_TYPE_SIZE
        !           108: #endif
        !           109: 
        !           110: #ifndef MAX_LONG_TYPE_SIZE
        !           111: #define MAX_LONG_TYPE_SIZE LONG_TYPE_SIZE
        !           112: #endif
        !           113: 
        !           114: #ifndef MAX_WCHAR_TYPE_SIZE
        !           115: #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
        !           116: #endif
        !           117: 
        !           118: /* Yield nonzero if adding two numbers with A's and B's signs can yield a
        !           119:    number with SUM's sign, where A, B, and SUM are all C integers.  */
        !           120: #define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0)
        !           121: 
        !           122: static void integer_overflow ();
        !           123: static long left_shift ();
        !           124: static long right_shift ();
        !           125: %}
        !           126: 
        !           127: %union {
        !           128:   struct constant {long value; int unsignedp;} integer;
        !           129:   struct name {U_CHAR *address; int length;} name;
        !           130:   struct arglist *keywords;
        !           131:   int voidval;
        !           132:   char *sval;
        !           133: }
        !           134: 
        !           135: %type <integer> exp exp1 start
        !           136: %type <keywords> keywords
        !           137: %token <integer> INT CHAR
        !           138: %token <name> NAME
        !           139: %token <integer> ERROR
        !           140: 
        !           141: %right '?' ':'
        !           142: %left ','
        !           143: %left OR
        !           144: %left AND
        !           145: %left '|'
        !           146: %left '^'
        !           147: %left '&'
        !           148: %left EQUAL NOTEQUAL
        !           149: %left '<' '>' LEQ GEQ
        !           150: %left LSH RSH
        !           151: %left '+' '-'
        !           152: %left '*' '/' '%'
        !           153: %right UNARY
        !           154: 
        !           155: /* %expect 40 */
        !           156: 
        !           157: %%
        !           158: 
        !           159: start   :      exp1
        !           160:                { expression_value = $1.value; }
        !           161:        ;
        !           162: 
        !           163: /* Expressions, including the comma operator.  */
        !           164: exp1   :       exp
        !           165:        |       exp1 ',' exp
        !           166:                        { if (pedantic)
        !           167:                            pedwarn ("comma operator in operand of `#if'");
        !           168:                          $$ = $3; }
        !           169:        ;
        !           170: 
        !           171: /* Expressions, not including the comma operator.  */
        !           172: exp    :       '-' exp    %prec UNARY
        !           173:                        { $$.value = - $2.value;
        !           174:                          if (($$.value & $2.value) < 0 && ! $2.unsignedp)
        !           175:                            integer_overflow ();
        !           176:                          $$.unsignedp = $2.unsignedp; }
        !           177:        |       '!' exp    %prec UNARY
        !           178:                        { $$.value = ! $2.value;
        !           179:                          $$.unsignedp = 0; }
        !           180:        |       '+' exp    %prec UNARY
        !           181:                        { $$ = $2; }
        !           182:        |       '~' exp    %prec UNARY
        !           183:                        { $$.value = ~ $2.value;
        !           184:                          $$.unsignedp = $2.unsignedp; }
        !           185:        |       '#' NAME
        !           186:                        { $$.value = check_assertion ($2.address, $2.length,
        !           187:                                                      0, NULL_PTR);
        !           188:                          $$.unsignedp = 0; }
        !           189:        |       '#' NAME
        !           190:                        { keyword_parsing = 1; }
        !           191:                '(' keywords ')'
        !           192:                        { $$.value = check_assertion ($2.address, $2.length,
        !           193:                                                      1, $5);
        !           194:                          keyword_parsing = 0;
        !           195:                          $$.unsignedp = 0; }
        !           196:        |       '(' exp1 ')'
        !           197:                        { $$ = $2; }
        !           198:        ;
        !           199: 
        !           200: /* Binary operators in order of decreasing precedence.  */
        !           201: exp    :       exp '*' exp
        !           202:                        { $$.unsignedp = $1.unsignedp || $3.unsignedp;
        !           203:                          if ($$.unsignedp)
        !           204:                            $$.value = (unsigned long) $1.value * $3.value;
        !           205:                          else
        !           206:                            {
        !           207:                              $$.value = $1.value * $3.value;
        !           208:                              if ($1.value
        !           209:                                  && ($$.value / $1.value != $3.value
        !           210:                                      || ($$.value & $1.value & $3.value) < 0))
        !           211:                                integer_overflow ();
        !           212:                            } }
        !           213:        |       exp '/' exp
        !           214:                        { if ($3.value == 0)
        !           215:                            {
        !           216:                              error ("division by zero in #if");
        !           217:                              $3.value = 1;
        !           218:                            }
        !           219:                          $$.unsignedp = $1.unsignedp || $3.unsignedp;
        !           220:                          if ($$.unsignedp)
        !           221:                            $$.value = (unsigned long) $1.value / $3.value;
        !           222:                          else
        !           223:                            {
        !           224:                              $$.value = $1.value / $3.value;
        !           225:                              if (($$.value & $1.value & $3.value) < 0)
        !           226:                                integer_overflow ();
        !           227:                            } }
        !           228:        |       exp '%' exp
        !           229:                        { if ($3.value == 0)
        !           230:                            {
        !           231:                              error ("division by zero in #if");
        !           232:                              $3.value = 1;
        !           233:                            }
        !           234:                          $$.unsignedp = $1.unsignedp || $3.unsignedp;
        !           235:                          if ($$.unsignedp)
        !           236:                            $$.value = (unsigned long) $1.value % $3.value;
        !           237:                          else
        !           238:                            $$.value = $1.value % $3.value; }
        !           239:        |       exp '+' exp
        !           240:                        { $$.value = $1.value + $3.value;
        !           241:                          $$.unsignedp = $1.unsignedp || $3.unsignedp;
        !           242:                          if (! $$.unsignedp
        !           243:                              && ! possible_sum_sign ($1.value, $3.value,
        !           244:                                                      $$.value))
        !           245:                            integer_overflow (); }
        !           246:        |       exp '-' exp
        !           247:                        { $$.value = $1.value - $3.value;
        !           248:                          $$.unsignedp = $1.unsignedp || $3.unsignedp;
        !           249:                          if (! $$.unsignedp
        !           250:                              && ! possible_sum_sign ($$.value, $3.value,
        !           251:                                                      $1.value))
        !           252:                            integer_overflow (); }
        !           253:        |       exp LSH exp
        !           254:                        { $$.unsignedp = $1.unsignedp;
        !           255:                          if ($3.value < 0 && ! $3.unsignedp)
        !           256:                            $$.value = right_shift (&$1, -$3.value);
        !           257:                          else
        !           258:                            $$.value = left_shift (&$1, $3.value); }
        !           259:        |       exp RSH exp
        !           260:                        { $$.unsignedp = $1.unsignedp;
        !           261:                          if ($3.value < 0 && ! $3.unsignedp)
        !           262:                            $$.value = left_shift (&$1, -$3.value);
        !           263:                          else
        !           264:                            $$.value = right_shift (&$1, $3.value); }
        !           265:        |       exp EQUAL exp
        !           266:                        { $$.value = ($1.value == $3.value);
        !           267:                          $$.unsignedp = 0; }
        !           268:        |       exp NOTEQUAL exp
        !           269:                        { $$.value = ($1.value != $3.value);
        !           270:                          $$.unsignedp = 0; }
        !           271:        |       exp LEQ exp
        !           272:                        { $$.unsignedp = 0;
        !           273:                          if ($1.unsignedp || $3.unsignedp)
        !           274:                            $$.value = (unsigned long) $1.value <= $3.value;
        !           275:                          else
        !           276:                            $$.value = $1.value <= $3.value; }
        !           277:        |       exp GEQ exp
        !           278:                        { $$.unsignedp = 0;
        !           279:                          if ($1.unsignedp || $3.unsignedp)
        !           280:                            $$.value = (unsigned long) $1.value >= $3.value;
        !           281:                          else
        !           282:                            $$.value = $1.value >= $3.value; }
        !           283:        |       exp '<' exp
        !           284:                        { $$.unsignedp = 0;
        !           285:                          if ($1.unsignedp || $3.unsignedp)
        !           286:                            $$.value = (unsigned long) $1.value < $3.value;
        !           287:                          else
        !           288:                            $$.value = $1.value < $3.value; }
        !           289:        |       exp '>' exp
        !           290:                        { $$.unsignedp = 0;
        !           291:                          if ($1.unsignedp || $3.unsignedp)
        !           292:                            $$.value = (unsigned long) $1.value > $3.value;
        !           293:                          else
        !           294:                            $$.value = $1.value > $3.value; }
        !           295:        |       exp '&' exp
        !           296:                        { $$.value = $1.value & $3.value;
        !           297:                          $$.unsignedp = $1.unsignedp || $3.unsignedp; }
        !           298:        |       exp '^' exp
        !           299:                        { $$.value = $1.value ^ $3.value;
        !           300:                          $$.unsignedp = $1.unsignedp || $3.unsignedp; }
        !           301:        |       exp '|' exp
        !           302:                        { $$.value = $1.value | $3.value;
        !           303:                          $$.unsignedp = $1.unsignedp || $3.unsignedp; }
        !           304:        |       exp AND exp
        !           305:                        { $$.value = ($1.value && $3.value);
        !           306:                          $$.unsignedp = 0; }
        !           307:        |       exp OR exp
        !           308:                        { $$.value = ($1.value || $3.value);
        !           309:                          $$.unsignedp = 0; }
        !           310:        |       exp '?' exp ':' exp
        !           311:                        { $$.value = $1.value ? $3.value : $5.value;
        !           312:                          $$.unsignedp = $3.unsignedp || $5.unsignedp; }
        !           313:        |       INT
        !           314:                        { $$ = yylval.integer; }
        !           315:        |       CHAR
        !           316:                        { $$ = yylval.integer; }
        !           317:        |       NAME
        !           318:                        { $$.value = 0;
        !           319:                          $$.unsignedp = 0; }
        !           320:        ;
        !           321: 
        !           322: keywords :
        !           323:                        { $$ = 0; } 
        !           324:        |       '(' keywords ')' keywords
        !           325:                        { struct arglist *temp;
        !           326:                          $$ = (struct arglist *) xmalloc (sizeof (struct arglist));
        !           327:                          $$->next = $2;
        !           328:                          $$->name = (U_CHAR *) "(";
        !           329:                          $$->length = 1;
        !           330:                          temp = $$;
        !           331:                          while (temp != 0 && temp->next != 0)
        !           332:                            temp = temp->next;
        !           333:                          temp->next = (struct arglist *) xmalloc (sizeof (struct arglist));
        !           334:                          temp->next->next = $4;
        !           335:                          temp->next->name = (U_CHAR *) ")";
        !           336:                          temp->next->length = 1; }
        !           337:        |       NAME keywords
        !           338:                        { $$ = (struct arglist *) xmalloc (sizeof (struct arglist));
        !           339:                          $$->name = $1.address;
        !           340:                          $$->length = $1.length;
        !           341:                          $$->next = $2; } 
        !           342:        ;
        !           343: %%
        !           344: 
        !           345: /* During parsing of a C expression, the pointer to the next character
        !           346:    is in this variable.  */
        !           347: 
        !           348: static char *lexptr;
        !           349: 
        !           350: /* Take care of parsing a number (anything that starts with a digit).
        !           351:    Set yylval and return the token type; update lexptr.
        !           352:    LEN is the number of characters in it.  */
        !           353: 
        !           354: /* maybe needs to actually deal with floating point numbers */
        !           355: 
        !           356: int
        !           357: parse_number (olen)
        !           358:      int olen;
        !           359: {
        !           360:   register char *p = lexptr;
        !           361:   register int c;
        !           362:   register unsigned long n = 0, nd, ULONG_MAX_over_base;
        !           363:   register int base = 10;
        !           364:   register int len = olen;
        !           365:   register int overflow = 0;
        !           366:   register int digit, largest_digit = 0;
        !           367:   int spec_long = 0;
        !           368: 
        !           369:   for (c = 0; c < len; c++)
        !           370:     if (p[c] == '.') {
        !           371:       /* It's a float since it contains a point.  */
        !           372:       yyerror ("floating point numbers not allowed in #if expressions");
        !           373:       return ERROR;
        !           374:     }
        !           375: 
        !           376:   yylval.integer.unsignedp = 0;
        !           377: 
        !           378:   if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) {
        !           379:     p += 2;
        !           380:     base = 16;
        !           381:     len -= 2;
        !           382:   }
        !           383:   else if (*p == '0')
        !           384:     base = 8;
        !           385: 
        !           386:   ULONG_MAX_over_base = (unsigned long) -1 / base;
        !           387: 
        !           388:   for (; len > 0; len--) {
        !           389:     c = *p++;
        !           390: 
        !           391:     if (c >= '0' && c <= '9')
        !           392:       digit = c - '0';
        !           393:     else if (base == 16 && c >= 'a' && c <= 'f')
        !           394:       digit = c - 'a' + 10;
        !           395:     else if (base == 16 && c >= 'A' && c <= 'F')
        !           396:       digit = c - 'A' + 10;
        !           397:     else {
        !           398:       /* `l' means long, and `u' means unsigned.  */
        !           399:       while (1) {
        !           400:        if (c == 'l' || c == 'L')
        !           401:          {
        !           402:            if (spec_long)
        !           403:              yyerror ("two `l's in integer constant");
        !           404:            spec_long = 1;
        !           405:          }
        !           406:        else if (c == 'u' || c == 'U')
        !           407:          {
        !           408:            if (yylval.integer.unsignedp)
        !           409:              yyerror ("two `u's in integer constant");
        !           410:            yylval.integer.unsignedp = 1;
        !           411:          }
        !           412:        else
        !           413:          break;
        !           414: 
        !           415:        if (--len == 0)
        !           416:          break;
        !           417:        c = *p++;
        !           418:       }
        !           419:       /* Don't look for any more digits after the suffixes.  */
        !           420:       break;
        !           421:     }
        !           422:     if (largest_digit < digit)
        !           423:       largest_digit = digit;
        !           424:     nd = n * base + digit;
        !           425:     overflow |= ULONG_MAX_over_base < n | nd < n;
        !           426:     n = nd;
        !           427:   }
        !           428: 
        !           429:   if (len != 0) {
        !           430:     yyerror ("Invalid number in #if expression");
        !           431:     return ERROR;
        !           432:   }
        !           433: 
        !           434:   if (base <= largest_digit)
        !           435:     warning ("integer constant contains digits beyond the radix");
        !           436: 
        !           437:   if (overflow)
        !           438:     warning ("integer constant out of range");
        !           439: 
        !           440:   /* If too big to be signed, consider it unsigned.  */
        !           441:   if ((long) n < 0 && ! yylval.integer.unsignedp)
        !           442:     {
        !           443:       if (base == 10)
        !           444:        warning ("integer constant is so large that it is unsigned");
        !           445:       yylval.integer.unsignedp = 1;
        !           446:     }
        !           447: 
        !           448:   lexptr = p;
        !           449:   yylval.integer.value = n;
        !           450:   return INT;
        !           451: }
        !           452: 
        !           453: struct token {
        !           454:   char *operator;
        !           455:   int token;
        !           456: };
        !           457: 
        !           458: static struct token tokentab2[] = {
        !           459:   {"&&", AND},
        !           460:   {"||", OR},
        !           461:   {"<<", LSH},
        !           462:   {">>", RSH},
        !           463:   {"==", EQUAL},
        !           464:   {"!=", NOTEQUAL},
        !           465:   {"<=", LEQ},
        !           466:   {">=", GEQ},
        !           467:   {"++", ERROR},
        !           468:   {"--", ERROR},
        !           469:   {NULL, ERROR}
        !           470: };
        !           471: 
        !           472: /* Read one token, getting characters through lexptr.  */
        !           473: 
        !           474: int
        !           475: yylex ()
        !           476: {
        !           477:   register int c;
        !           478:   register int namelen;
        !           479:   register unsigned char *tokstart;
        !           480:   register struct token *toktab;
        !           481:   int wide_flag;
        !           482: 
        !           483:  retry:
        !           484: 
        !           485:   tokstart = (unsigned char *) lexptr;
        !           486:   c = *tokstart;
        !           487:   /* See if it is a special token of length 2.  */
        !           488:   if (! keyword_parsing)
        !           489:     for (toktab = tokentab2; toktab->operator != NULL; toktab++)
        !           490:       if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) {
        !           491:        lexptr += 2;
        !           492:        if (toktab->token == ERROR)
        !           493:          {
        !           494:            char *buf = (char *) alloca (40);
        !           495:            sprintf (buf, "`%s' not allowed in operand of `#if'", toktab->operator);
        !           496:            yyerror (buf);
        !           497:          }
        !           498:        return toktab->token;
        !           499:       }
        !           500: 
        !           501:   switch (c) {
        !           502:   case 0:
        !           503:     return 0;
        !           504:     
        !           505:   case ' ':
        !           506:   case '\t':
        !           507:   case '\r':
        !           508:   case '\n':
        !           509:     lexptr++;
        !           510:     goto retry;
        !           511:     
        !           512:   case 'L':
        !           513:     /* Capital L may start a wide-string or wide-character constant.  */
        !           514:     if (lexptr[1] == '\'')
        !           515:       {
        !           516:        lexptr++;
        !           517:        wide_flag = 1;
        !           518:        goto char_constant;
        !           519:       }
        !           520:     if (lexptr[1] == '"')
        !           521:       {
        !           522:        lexptr++;
        !           523:        wide_flag = 1;
        !           524:        goto string_constant;
        !           525:       }
        !           526:     break;
        !           527: 
        !           528:   case '\'':
        !           529:     wide_flag = 0;
        !           530:   char_constant:
        !           531:     lexptr++;
        !           532:     if (keyword_parsing) {
        !           533:       char *start_ptr = lexptr - 1;
        !           534:       while (1) {
        !           535:        c = *lexptr++;
        !           536:        if (c == '\\')
        !           537:          c = parse_escape (&lexptr);
        !           538:        else if (c == '\'')
        !           539:          break;
        !           540:       }
        !           541:       yylval.name.address = tokstart;
        !           542:       yylval.name.length = lexptr - start_ptr;
        !           543:       return NAME;
        !           544:     }
        !           545: 
        !           546:     /* This code for reading a character constant
        !           547:        handles multicharacter constants and wide characters.
        !           548:        It is mostly copied from c-lex.c.  */
        !           549:     {
        !           550:       register int result = 0;
        !           551:       register num_chars = 0;
        !           552:       unsigned width = MAX_CHAR_TYPE_SIZE;
        !           553:       int max_chars;
        !           554:       char *token_buffer;
        !           555: 
        !           556:       if (wide_flag)
        !           557:        {
        !           558:          width = MAX_WCHAR_TYPE_SIZE;
        !           559: #ifdef MULTIBYTE_CHARS
        !           560:          max_chars = MB_CUR_MAX;
        !           561: #else
        !           562:          max_chars = 1;
        !           563: #endif
        !           564:        }
        !           565:       else
        !           566:        max_chars = MAX_LONG_TYPE_SIZE / width;
        !           567: 
        !           568:       token_buffer = (char *) alloca (max_chars + 1);
        !           569: 
        !           570:       while (1)
        !           571:        {
        !           572:          c = *lexptr++;
        !           573: 
        !           574:          if (c == '\'' || c == EOF)
        !           575:            break;
        !           576: 
        !           577:          if (c == '\\')
        !           578:            {
        !           579:              c = parse_escape (&lexptr);
        !           580:              if (width < HOST_BITS_PER_INT
        !           581:                  && (unsigned) c >= (1 << width))
        !           582:                pedwarn ("escape sequence out of range for character");
        !           583:            }
        !           584: 
        !           585:          num_chars++;
        !           586: 
        !           587:          /* Merge character into result; ignore excess chars.  */
        !           588:          if (num_chars < max_chars + 1)
        !           589:            {
        !           590:              if (width < HOST_BITS_PER_INT)
        !           591:                result = (result << width) | (c & ((1 << width) - 1));
        !           592:              else
        !           593:                result = c;
        !           594:              token_buffer[num_chars - 1] = c;
        !           595:            }
        !           596:        }
        !           597: 
        !           598:       token_buffer[num_chars] = 0;
        !           599: 
        !           600:       if (c != '\'')
        !           601:        error ("malformatted character constant");
        !           602:       else if (num_chars == 0)
        !           603:        error ("empty character constant");
        !           604:       else if (num_chars > max_chars)
        !           605:        {
        !           606:          num_chars = max_chars;
        !           607:          error ("character constant too long");
        !           608:        }
        !           609:       else if (num_chars != 1 && ! traditional)
        !           610:        warning ("multi-character character constant");
        !           611: 
        !           612:       /* If char type is signed, sign-extend the constant.  */
        !           613:       if (! wide_flag)
        !           614:        {
        !           615:          int num_bits = num_chars * width;
        !           616: 
        !           617:          if (lookup ("__CHAR_UNSIGNED__", sizeof ("__CHAR_UNSIGNED__")-1, -1)
        !           618:              || ((result >> (num_bits - 1)) & 1) == 0)
        !           619:            yylval.integer.value
        !           620:              = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
        !           621:          else
        !           622:            yylval.integer.value
        !           623:              = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
        !           624:        }
        !           625:       else
        !           626:        {
        !           627: #ifdef MULTIBYTE_CHARS
        !           628:          /* Set the initial shift state and convert the next sequence.  */
        !           629:          result = 0;
        !           630:          /* In all locales L'\0' is zero and mbtowc will return zero,
        !           631:             so don't use it.  */
        !           632:          if (num_chars > 1
        !           633:              || (num_chars == 1 && token_buffer[0] != '\0'))
        !           634:            {
        !           635:              wchar_t wc;
        !           636:              (void) mbtowc (NULL_PTR, NULL_PTR, 0);
        !           637:              if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
        !           638:                result = wc;
        !           639:              else
        !           640:                warning ("Ignoring invalid multibyte character");
        !           641:            }
        !           642: #endif
        !           643:          yylval.integer.value = result;
        !           644:        }
        !           645:     }
        !           646: 
        !           647:     /* This is always a signed type.  */
        !           648:     yylval.integer.unsignedp = 0;
        !           649:     
        !           650:     return CHAR;
        !           651: 
        !           652:     /* some of these chars are invalid in constant expressions;
        !           653:        maybe do something about them later */
        !           654:   case '/':
        !           655:   case '+':
        !           656:   case '-':
        !           657:   case '*':
        !           658:   case '%':
        !           659:   case '|':
        !           660:   case '&':
        !           661:   case '^':
        !           662:   case '~':
        !           663:   case '!':
        !           664:   case '@':
        !           665:   case '<':
        !           666:   case '>':
        !           667:   case '[':
        !           668:   case ']':
        !           669:   case '.':
        !           670:   case '?':
        !           671:   case ':':
        !           672:   case '=':
        !           673:   case '{':
        !           674:   case '}':
        !           675:   case ',':
        !           676:   case '#':
        !           677:     if (keyword_parsing)
        !           678:       break;
        !           679:   case '(':
        !           680:   case ')':
        !           681:     lexptr++;
        !           682:     return c;
        !           683: 
        !           684:   case '"':
        !           685:   string_constant:
        !           686:     if (keyword_parsing) {
        !           687:       char *start_ptr = lexptr;
        !           688:       lexptr++;
        !           689:       while (1) {
        !           690:        c = *lexptr++;
        !           691:        if (c == '\\')
        !           692:          c = parse_escape (&lexptr);
        !           693:        else if (c == '"')
        !           694:          break;
        !           695:       }
        !           696:       yylval.name.address = tokstart;
        !           697:       yylval.name.length = lexptr - start_ptr;
        !           698:       return NAME;
        !           699:     }
        !           700:     yyerror ("string constants not allowed in #if expressions");
        !           701:     return ERROR;
        !           702:   }
        !           703: 
        !           704:   if (c >= '0' && c <= '9' && !keyword_parsing) {
        !           705:     /* It's a number */
        !           706:     for (namelen = 0;
        !           707:         c = tokstart[namelen], is_idchar[c] || c == '.'; 
        !           708:         namelen++)
        !           709:       ;
        !           710:     return parse_number (namelen);
        !           711:   }
        !           712: 
        !           713:   /* It is a name.  See how long it is.  */
        !           714: 
        !           715:   if (keyword_parsing) {
        !           716:     for (namelen = 0;; namelen++) {
        !           717:       if (is_hor_space[tokstart[namelen]])
        !           718:        break;
        !           719:       if (tokstart[namelen] == '(' || tokstart[namelen] == ')')
        !           720:        break;
        !           721:       if (tokstart[namelen] == '"' || tokstart[namelen] == '\'')
        !           722:        break;
        !           723:     }
        !           724:   } else {
        !           725:     if (!is_idstart[c]) {
        !           726:       yyerror ("Invalid token in expression");
        !           727:       return ERROR;
        !           728:     }
        !           729: 
        !           730:     for (namelen = 0; is_idchar[tokstart[namelen]]; namelen++)
        !           731:       ;
        !           732:   }
        !           733:   
        !           734:   lexptr += namelen;
        !           735:   yylval.name.address = tokstart;
        !           736:   yylval.name.length = namelen;
        !           737:   return NAME;
        !           738: }
        !           739: 
        !           740: 
        !           741: /* Parse a C escape sequence.  STRING_PTR points to a variable
        !           742:    containing a pointer to the string to parse.  That pointer
        !           743:    is updated past the characters we use.  The value of the
        !           744:    escape sequence is returned.
        !           745: 
        !           746:    A negative value means the sequence \ newline was seen,
        !           747:    which is supposed to be equivalent to nothing at all.
        !           748: 
        !           749:    If \ is followed by a null character, we return a negative
        !           750:    value and leave the string pointer pointing at the null character.
        !           751: 
        !           752:    If \ is followed by 000, we return 0 and leave the string pointer
        !           753:    after the zeros.  A value of 0 does not mean end of string.  */
        !           754: 
        !           755: int
        !           756: parse_escape (string_ptr)
        !           757:      char **string_ptr;
        !           758: {
        !           759:   register int c = *(*string_ptr)++;
        !           760:   switch (c)
        !           761:     {
        !           762:     case 'a':
        !           763:       return TARGET_BELL;
        !           764:     case 'b':
        !           765:       return TARGET_BS;
        !           766:     case 'e':
        !           767:     case 'E':
        !           768:       if (pedantic)
        !           769:        pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c);
        !           770:       return 033;
        !           771:     case 'f':
        !           772:       return TARGET_FF;
        !           773:     case 'n':
        !           774:       return TARGET_NEWLINE;
        !           775:     case 'r':
        !           776:       return TARGET_CR;
        !           777:     case 't':
        !           778:       return TARGET_TAB;
        !           779:     case 'v':
        !           780:       return TARGET_VT;
        !           781:     case '\n':
        !           782:       return -2;
        !           783:     case 0:
        !           784:       (*string_ptr)--;
        !           785:       return 0;
        !           786:       
        !           787:     case '0':
        !           788:     case '1':
        !           789:     case '2':
        !           790:     case '3':
        !           791:     case '4':
        !           792:     case '5':
        !           793:     case '6':
        !           794:     case '7':
        !           795:       {
        !           796:        register int i = c - '0';
        !           797:        register int count = 0;
        !           798:        while (++count < 3)
        !           799:          {
        !           800:            c = *(*string_ptr)++;
        !           801:            if (c >= '0' && c <= '7')
        !           802:              i = (i << 3) + c - '0';
        !           803:            else
        !           804:              {
        !           805:                (*string_ptr)--;
        !           806:                break;
        !           807:              }
        !           808:          }
        !           809:        if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
        !           810:          {
        !           811:            i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
        !           812:            warning ("octal character constant does not fit in a byte");
        !           813:          }
        !           814:        return i;
        !           815:       }
        !           816:     case 'x':
        !           817:       {
        !           818:        register unsigned i = 0, overflow = 0, digits_found = 0, digit;
        !           819:        for (;;)
        !           820:          {
        !           821:            c = *(*string_ptr)++;
        !           822:            if (c >= '0' && c <= '9')
        !           823:              digit = c - '0';
        !           824:            else if (c >= 'a' && c <= 'f')
        !           825:              digit = c - 'a' + 10;
        !           826:            else if (c >= 'A' && c <= 'F')
        !           827:              digit = c - 'A' + 10;
        !           828:            else
        !           829:              {
        !           830:                (*string_ptr)--;
        !           831:                break;
        !           832:              }
        !           833:            overflow |= i ^ (i << 4 >> 4);
        !           834:            i = (i << 4) + digit;
        !           835:            digits_found = 1;
        !           836:          }
        !           837:        if (!digits_found)
        !           838:          yyerror ("\\x used with no following hex digits");
        !           839:        if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1)))
        !           840:          {
        !           841:            i &= (1 << BITS_PER_UNIT) - 1;
        !           842:            warning ("hex character constant does not fit in a byte");
        !           843:          }
        !           844:        return i;
        !           845:       }
        !           846:     default:
        !           847:       return c;
        !           848:     }
        !           849: }
        !           850: 
        !           851: void
        !           852: yyerror (s)
        !           853:      char *s;
        !           854: {
        !           855:   error (s);
        !           856:   longjmp (parse_return_error, 1);
        !           857: }
        !           858: 
        !           859: static void
        !           860: integer_overflow ()
        !           861: {
        !           862:   if (pedantic)
        !           863:     pedwarn ("integer overflow in preprocessor expression");
        !           864: }
        !           865: 
        !           866: static long
        !           867: left_shift (a, b)
        !           868:      struct constant *a;
        !           869:      unsigned long b;
        !           870: {
        !           871:   if (b >= HOST_BITS_PER_LONG)
        !           872:     {
        !           873:       if (! a->unsignedp && a->value != 0)
        !           874:        integer_overflow ();
        !           875:       return 0;
        !           876:     }
        !           877:   else if (a->unsignedp)
        !           878:     return (unsigned long) a->value << b;
        !           879:   else
        !           880:     {
        !           881:       long l = a->value << b;
        !           882:       if (l >> b != a->value)
        !           883:        integer_overflow ();
        !           884:       return l;
        !           885:     }
        !           886: }
        !           887: 
        !           888: static long
        !           889: right_shift (a, b)
        !           890:      struct constant *a;
        !           891:      unsigned long b;
        !           892: {
        !           893:   if (b >= HOST_BITS_PER_LONG)
        !           894:     return a->unsignedp ? 0 : a->value >> (HOST_BITS_PER_LONG - 1);
        !           895:   else if (a->unsignedp)
        !           896:     return (unsigned long) a->value >> b;
        !           897:   else
        !           898:     return a->value >> b;
        !           899: }
        !           900: 
        !           901: /* This page contains the entry point to this file.  */
        !           902: 
        !           903: /* Parse STRING as an expression, and complain if this fails
        !           904:    to use up all of the contents of STRING.  */
        !           905: /* We do not support C comments.  They should be removed before
        !           906:    this function is called.  */
        !           907: 
        !           908: int
        !           909: parse_c_expression (string)
        !           910:      char *string;
        !           911: {
        !           912:   lexptr = string;
        !           913:   
        !           914:   if (lexptr == 0 || *lexptr == 0) {
        !           915:     error ("empty #if expression");
        !           916:     return 0;                  /* don't include the #if group */
        !           917:   }
        !           918: 
        !           919:   /* if there is some sort of scanning error, just return 0 and assume
        !           920:      the parsing routine has printed an error message somewhere.
        !           921:      there is surely a better thing to do than this.     */
        !           922:   if (setjmp (parse_return_error))
        !           923:     return 0;
        !           924: 
        !           925:   if (yyparse ())
        !           926:     return 0;                  /* actually this is never reached
        !           927:                                   the way things stand. */
        !           928:   if (*lexptr)
        !           929:     error ("Junk after end of expression.");
        !           930: 
        !           931:   return expression_value;     /* set by yyparse () */
        !           932: }
        !           933: 
        !           934: #ifdef TEST_EXP_READER
        !           935: extern int yydebug;
        !           936: 
        !           937: /* Main program for testing purposes.  */
        !           938: int
        !           939: main ()
        !           940: {
        !           941:   int n, c;
        !           942:   char buf[1024];
        !           943: 
        !           944: /*
        !           945:   yydebug = 1;
        !           946: */
        !           947:   initialize_random_junk ();
        !           948: 
        !           949:   for (;;) {
        !           950:     printf ("enter expression: ");
        !           951:     n = 0;
        !           952:     while ((buf[n] = getchar ()) != '\n' && buf[n] != EOF)
        !           953:       n++;
        !           954:     if (buf[n] == EOF)
        !           955:       break;
        !           956:     buf[n] = '\0';
        !           957:     printf ("parser returned %d\n", parse_c_expression (buf));
        !           958:   }
        !           959: 
        !           960:   return 0;
        !           961: }
        !           962: 
        !           963: /* table to tell if char can be part of a C identifier. */
        !           964: unsigned char is_idchar[256];
        !           965: /* table to tell if char can be first char of a c identifier. */
        !           966: unsigned char is_idstart[256];
        !           967: /* table to tell if c is horizontal space.  isspace () thinks that
        !           968:    newline is space; this is not a good idea for this program. */
        !           969: char is_hor_space[256];
        !           970: 
        !           971: /*
        !           972:  * initialize random junk in the hash table and maybe other places
        !           973:  */
        !           974: initialize_random_junk ()
        !           975: {
        !           976:   register int i;
        !           977: 
        !           978:   /*
        !           979:    * Set up is_idchar and is_idstart tables.  These should be
        !           980:    * faster than saying (is_alpha (c) || c == '_'), etc.
        !           981:    * Must do set up these things before calling any routines tthat
        !           982:    * refer to them.
        !           983:    */
        !           984:   for (i = 'a'; i <= 'z'; i++) {
        !           985:     ++is_idchar[i - 'a' + 'A'];
        !           986:     ++is_idchar[i];
        !           987:     ++is_idstart[i - 'a' + 'A'];
        !           988:     ++is_idstart[i];
        !           989:   }
        !           990:   for (i = '0'; i <= '9'; i++)
        !           991:     ++is_idchar[i];
        !           992:   ++is_idchar['_'];
        !           993:   ++is_idstart['_'];
        !           994: #if DOLLARS_IN_IDENTIFIERS
        !           995:   ++is_idchar['$'];
        !           996:   ++is_idstart['$'];
        !           997: #endif
        !           998: 
        !           999:   /* horizontal space table */
        !          1000:   ++is_hor_space[' '];
        !          1001:   ++is_hor_space['\t'];
        !          1002: }
        !          1003: 
        !          1004: error (msg)
        !          1005: {
        !          1006:   printf ("error: %s\n", msg);
        !          1007: }
        !          1008: 
        !          1009: warning (msg)
        !          1010: {
        !          1011:   printf ("warning: %s\n", msg);
        !          1012: }
        !          1013: 
        !          1014: struct hashnode *
        !          1015: lookup (name, len, hash)
        !          1016:      char *name;
        !          1017:      int len;
        !          1018:      int hash;
        !          1019: {
        !          1020:   return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1);
        !          1021: }
        !          1022: #endif

unix.superglobalmegacorp.com

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