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

unix.superglobalmegacorp.com

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