Annotation of researchv10dc/cmd/gcc/cexp.y, revision 1.1

1.1     ! root        1: /* Parse C expressions for CCCP.
        !             2:    Copyright (C) 1987 Free Software Foundation.
        !             3: 
        !             4:                       NO WARRANTY
        !             5: 
        !             6:   BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
        !             7: NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
        !             8: WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
        !             9: RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
        !            10: WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
        !            11: BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
        !            12: FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY
        !            13: AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE
        !            14: DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
        !            15: CORRECTION.
        !            16: 
        !            17:  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
        !            18: STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
        !            19: WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
        !            20: LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
        !            21: OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
        !            22: USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
        !            23: DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
        !            24: A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
        !            25: PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
        !            26: DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
        !            27: 
        !            28:                GENERAL PUBLIC LICENSE TO COPY
        !            29: 
        !            30:   1. You may copy and distribute verbatim copies of this source file
        !            31: as you receive it, in any medium, provided that you conspicuously and
        !            32: appropriately publish on each copy a valid copyright notice "Copyright
        !            33: (C) 1987 Free Software Foundation"; and include following the
        !            34: copyright notice a verbatim copy of the above disclaimer of warranty
        !            35: and of this License.  You may charge a distribution fee for the
        !            36: physical act of transferring a copy.
        !            37: 
        !            38:   2. You may modify your copy or copies of this source file or
        !            39: any portion of it, and copy and distribute such modifications under
        !            40: the terms of Paragraph 1 above, provided that you also do the following:
        !            41: 
        !            42:     a) cause the modified files to carry prominent notices stating
        !            43:     that you changed the files and the date of any change; and
        !            44: 
        !            45:     b) cause the whole of any work that you distribute or publish,
        !            46:     that in whole or in part contains or is a derivative of this
        !            47:     program or any part thereof, to be licensed at no charge to all
        !            48:     third parties on terms identical to those contained in this
        !            49:     License Agreement (except that you may choose to grant more extensive
        !            50:     warranty protection to some or all third parties, at your option).
        !            51: 
        !            52:     c) You may charge a distribution fee for the physical act of
        !            53:     transferring a copy, and you may at your option offer warranty
        !            54:     protection in exchange for a fee.
        !            55: 
        !            56: Mere aggregation of another unrelated program with this program (or its
        !            57: derivative) on a volume of a storage or distribution medium does not bring
        !            58: the other program under the scope of these terms.
        !            59: 
        !            60:   3. You may copy and distribute this program (or a portion or derivative
        !            61: of it, under Paragraph 2) in object code or executable form under the terms
        !            62: of Paragraphs 1 and 2 above provided that you also do one of the following:
        !            63: 
        !            64:     a) accompany it with the complete corresponding machine-readable
        !            65:     source code, which must be distributed under the terms of
        !            66:     Paragraphs 1 and 2 above; or,
        !            67: 
        !            68:     b) accompany it with a written offer, valid for at least three
        !            69:     years, to give any third party free (except for a nominal
        !            70:     shipping charge) a complete machine-readable copy of the
        !            71:     corresponding source code, to be distributed under the terms of
        !            72:     Paragraphs 1 and 2 above; or,
        !            73: 
        !            74:     c) accompany it with the information you received as to where the
        !            75:     corresponding source code may be obtained.  (This alternative is
        !            76:     allowed only for noncommercial distribution and only if you
        !            77:     received the program in object code or executable form alone.)
        !            78: 
        !            79: For an executable file, complete source code means all the source code for
        !            80: all modules it contains; but, as a special exception, it need not include
        !            81: source code for modules which are standard libraries that accompany the
        !            82: operating system on which the executable file runs.
        !            83: 
        !            84:   4. You may not copy, sublicense, distribute or transfer this program
        !            85: except as expressly provided under this License Agreement.  Any attempt
        !            86: otherwise to copy, sublicense, distribute or transfer this program is void and
        !            87: your rights to use the program under this License agreement shall be
        !            88: automatically terminated.  However, parties who have received computer
        !            89: software programs from you with this License Agreement will not have
        !            90: their licenses terminated so long as such parties remain in full compliance.
        !            91: 
        !            92:   5. If you wish to incorporate parts of this program into other free
        !            93: programs whose distribution conditions are different, write to the Free
        !            94: Software Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not yet
        !            95: worked out a simple rule that can be stated here, but we will often permit
        !            96: this.  We will be guided by the two goals of preserving the free status of
        !            97: all derivatives of our free software and of promoting the sharing and reuse of
        !            98: software.
        !            99: 
        !           100: 
        !           101:  In other words, you are welcome to use, share and improve this program.
        !           102:  You are forbidden to forbid anyone else to use, share and improve
        !           103:  what you give them.   Help stamp out software-hoarding!
        !           104: 
        !           105:  Adapted from expread.y of GDB by Paul Rubin, July 1986.
        !           106: 
        !           107: /* Parse a C expression from text in a string  */
        !           108:    
        !           109: %{
        !           110: #include "config.h"
        !           111: #include <setjmp.h>
        !           112: /* #define YYDEBUG 1 */
        !           113: 
        !           114:   static int yylex ();
        !           115:   static yyerror ();
        !           116:   int expression_value;
        !           117: 
        !           118:   static jmp_buf parse_return_error;
        !           119: 
        !           120:   /* some external tables of character types */
        !           121:   extern unsigned char is_idstart[], is_idchar[];
        !           122: 
        !           123: %}
        !           124: 
        !           125: %union {
        !           126:   long lval;
        !           127:   int voidval;
        !           128:   char *sval;
        !           129: }
        !           130: 
        !           131: %type <lval> exp exp1 start
        !           132: %token <lval> INT CHAR
        !           133: %token <sval> NAME
        !           134: %token <lval> ERROR
        !           135: 
        !           136: %right '?' ':'
        !           137: %left ','
        !           138: %left OR
        !           139: %left AND
        !           140: %left '|'
        !           141: %left '^'
        !           142: %left '&'
        !           143: %left EQUAL NOTEQUAL
        !           144: %left '<' '>' LEQ GEQ
        !           145: %left LSH RSH
        !           146: %left '+' '-'
        !           147: %left '*' '/' '%'
        !           148: %right UNARY
        !           149: 
        !           150: /* %expect 40 */
        !           151: 
        !           152: %%
        !           153: 
        !           154: start   :      exp1
        !           155:                { expression_value = $1; }
        !           156:        ;
        !           157: 
        !           158: /* Expressions, including the comma operator.  */
        !           159: exp1   :       exp
        !           160:        |       exp1 ',' exp
        !           161:                        { $$ = $3; }
        !           162:        ;
        !           163: 
        !           164: /* Expressions, not including the comma operator.  */
        !           165: exp    :       '-' exp    %prec UNARY
        !           166:                        { $$ = - $2; }
        !           167:        |       '!' exp    %prec UNARY
        !           168:                        { $$ = ! $2; }
        !           169:        |       '~' exp    %prec UNARY
        !           170:                        { $$ = ~ $2; }
        !           171:        |       '(' exp1 ')'
        !           172:                        { $$ = $2; }
        !           173:        ;
        !           174: 
        !           175: /* Binary operators in order of decreasing precedence.  */
        !           176: exp    :       exp '*' exp
        !           177:                        { $$ = $1 * $3; }
        !           178:        |       exp '/' exp
        !           179:                        { $$ = $1 / $3; }
        !           180:        |       exp '%' exp
        !           181:                        { $$ = $1 % $3; }
        !           182:        |       exp '+' exp
        !           183:                        { $$ = $1 + $3; }
        !           184:        |       exp '-' exp
        !           185:                        { $$ = $1 - $3; }
        !           186:        |       exp LSH exp
        !           187:                        { $$ = $1 << $3; }
        !           188:        |       exp RSH exp
        !           189:                        { $$ = $1 >> $3; }
        !           190:        |       exp EQUAL exp
        !           191:                        { $$ = ($1 == $3); }
        !           192:        |       exp NOTEQUAL exp
        !           193:                        { $$ = ($1 != $3); }
        !           194:        |       exp LEQ exp
        !           195:                        { $$ = ($1 <= $3); }
        !           196:        |       exp GEQ exp
        !           197:                        { $$ = ($1 >= $3); }
        !           198:        |       exp '<' exp
        !           199:                        { $$ = ($1 < $3); }
        !           200:        |       exp '>' exp
        !           201:                        { $$ = ($1 > $3); }
        !           202:        |       exp '&' exp
        !           203:                        { $$ = ($1 & $3); }
        !           204:        |       exp '^' exp
        !           205:                        { $$ = ($1 ^ $3); }
        !           206:        |       exp '|' exp
        !           207:                        { $$ = ($1 | $3); }
        !           208:        |       exp AND exp
        !           209:                        { $$ = ($1 && $3); }
        !           210:        |       exp OR exp
        !           211:                        { $$ = ($1 || $3); }
        !           212:        |       exp '?' exp ':' exp
        !           213:                        { $$ = $1 ? $3 : $5; }
        !           214:        |       INT
        !           215:                        { $$ = yylval.lval; }
        !           216:        |       CHAR
        !           217:                        { $$ = yylval.lval; }
        !           218:        |       NAME
        !           219:                        { $$ = 0; }
        !           220:        ;
        !           221: %%
        !           222: 
        !           223: /* During parsing of a C expression, the pointer to the next character
        !           224:    is in this variable.  */
        !           225: 
        !           226: static char *lexptr;
        !           227: 
        !           228: /* Take care of parsing a number (anything that starts with a digit).
        !           229:    Set yylval and return the token type; update lexptr.
        !           230:    LEN is the number of characters in it.  */
        !           231: 
        !           232: /* maybe needs to actually deal with floating point numbers */
        !           233: 
        !           234: static int
        !           235: parse_number (olen)
        !           236:      int olen;
        !           237: {
        !           238:   register char *p = lexptr;
        !           239:   register long n = 0;
        !           240:   register int c;
        !           241:   register int base = 10;
        !           242:   register len = olen;
        !           243:   char *err_copy;
        !           244: 
        !           245:   extern double atof ();
        !           246: 
        !           247:   for (c = 0; c < len; c++)
        !           248:     if (p[c] == '.') {
        !           249:       /* It's a float since it contains a point.  */
        !           250:       yyerror ("floating point numbers not allowed in #if expressions");
        !           251:       return ERROR;
        !           252:       
        !           253: /* ****************
        !           254:         yylval.dval = atof (p);
        !           255:         lexptr += len;
        !           256:         return FLOAT;
        !           257:                 ****************  */
        !           258:     }
        !           259:   
        !           260:   if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) {
        !           261:     p += 2;
        !           262:     base = 16;
        !           263:     len -= 2;
        !           264:   }
        !           265:   else if (*p == '0')
        !           266:     base = 8;
        !           267:   
        !           268:   while (len-- > 0) {
        !           269:     c = *p++;
        !           270:     n *= base;
        !           271:     if (c >= '0' && c <= '9')
        !           272:       n += c - '0';
        !           273:     else {
        !           274:       if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
        !           275:       if (base == 16 && c >= 'a' && c <= 'f')
        !           276:        n += c - 'a' + 10;
        !           277:       else if (len == 0 && c == 'l')
        !           278:        ;
        !           279:       else {
        !           280:        yyerror ("Invalid number in #if expression");
        !           281:        return ERROR;
        !           282:       }
        !           283:     }
        !           284:   }
        !           285: 
        !           286:   lexptr = p;
        !           287:   yylval.lval = n;
        !           288:   return INT;
        !           289: }
        !           290: 
        !           291: struct token {
        !           292:   char *operator;
        !           293:   int token;
        !           294: };
        !           295: 
        !           296: #define NULL 0
        !           297: 
        !           298: static struct token tokentab2[] = {
        !           299:   {"&&", AND},
        !           300:   {"||", OR},
        !           301:   {"<<", LSH},
        !           302:   {">>", RSH},
        !           303:   {"==", EQUAL},
        !           304:   {"!=", NOTEQUAL},
        !           305:   {"<=", LEQ},
        !           306:   {">=", GEQ},
        !           307:   {NULL, ERROR}
        !           308: };
        !           309: 
        !           310: /* Read one token, getting characters through lexptr.  */
        !           311: 
        !           312: static int
        !           313: yylex ()
        !           314: {
        !           315:   register int c;
        !           316:   register int namelen;
        !           317:   register char *tokstart;
        !           318:   register struct token *toktab;
        !           319: 
        !           320:  retry:
        !           321: 
        !           322:   tokstart = lexptr;
        !           323:   c = *tokstart;
        !           324:   /* See if it is a special token of length 2.  */
        !           325:   for (toktab = tokentab2; toktab->operator != NULL; toktab++)
        !           326:     if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) {
        !           327:       lexptr += 2;
        !           328:       return toktab->token;
        !           329:     }
        !           330: 
        !           331:   switch (c) {
        !           332:   case 0:
        !           333:     return 0;
        !           334:     
        !           335:   case ' ':
        !           336:   case '\t':
        !           337:   case '\n':
        !           338:     lexptr++;
        !           339:     goto retry;
        !           340:     
        !           341:   case '\'':
        !           342:     lexptr++;
        !           343:     c = *lexptr++;
        !           344:     if (c == '\\')
        !           345:       c = parse_escape (&lexptr);
        !           346:     yylval.lval = c;
        !           347:     c = *lexptr++;
        !           348:     if (c != '\'') {
        !           349:       yyerror ("Invalid character constant in #if");
        !           350:       return ERROR;
        !           351:     }
        !           352:     
        !           353:     return CHAR;
        !           354: 
        !           355:     /* some of these chars are invalid in constant expressions;
        !           356:        maybe do something about them later */
        !           357:   case '/':
        !           358:   case '+':
        !           359:   case '-':
        !           360:   case '*':
        !           361:   case '%':
        !           362:   case '|':
        !           363:   case '&':
        !           364:   case '^':
        !           365:   case '~':
        !           366:   case '!':
        !           367:   case '@':
        !           368:   case '<':
        !           369:   case '>':
        !           370:   case '(':
        !           371:   case ')':
        !           372:   case '[':
        !           373:   case ']':
        !           374:   case '.':
        !           375:   case '?':
        !           376:   case ':':
        !           377:   case '=':
        !           378:   case '{':
        !           379:   case '}':
        !           380:   case ',':
        !           381:     lexptr++;
        !           382:     return c;
        !           383:     
        !           384:   case '"':
        !           385:     yyerror ("double quoted strings not allowed in #if expressions");
        !           386:     return ERROR;
        !           387:   }
        !           388:   if (c >= '0' && c <= '9') {
        !           389:     /* It's a number */
        !           390:     for (namelen = 0;
        !           391:         c = tokstart[namelen], is_idchar[c] || c == '.'; 
        !           392:         namelen++)
        !           393:       ;
        !           394:     return parse_number (namelen);
        !           395:   }
        !           396:   
        !           397:   if (!is_idstart[c]) {
        !           398:     yyerror ("Invalid token in expression");
        !           399:     return ERROR;
        !           400:   }
        !           401:   
        !           402:   /* It is a name.  See how long it is.  */
        !           403:   
        !           404:   for (namelen = 0; is_idchar[tokstart[namelen]]; namelen++)
        !           405:     ;
        !           406:   
        !           407:   lexptr += namelen;
        !           408:   return NAME;
        !           409: }
        !           410: 
        !           411: 
        !           412: /* Parse a C escape sequence.  STRING_PTR points to a variable
        !           413:    containing a pointer to the string to parse.  That pointer
        !           414:    is updated past the characters we use.  The value of the
        !           415:    escape sequence is returned.
        !           416: 
        !           417:    A negative value means the sequence \ newline was seen,
        !           418:    which is supposed to be equivalent to nothing at all.
        !           419: 
        !           420:    If \ is followed by a null character, we return a negative
        !           421:    value and leave the string pointer pointing at the null character.
        !           422: 
        !           423:    If \ is followed by 000, we return 0 and leave the string pointer
        !           424:    after the zeros.  A value of 0 does not mean end of string.  */
        !           425: 
        !           426: static int
        !           427: parse_escape (string_ptr)
        !           428:      char **string_ptr;
        !           429: {
        !           430:   register int c = *(*string_ptr)++;
        !           431:   switch (c)
        !           432:     {
        !           433:     case 'a':
        !           434:       return '\a';
        !           435:     case 'b':
        !           436:       return '\b';
        !           437:     case 'e':
        !           438:       return 033;
        !           439:     case 'f':
        !           440:       return '\f';
        !           441:     case 'n':
        !           442:       return '\n';
        !           443:     case 'r':
        !           444:       return '\r';
        !           445:     case 't':
        !           446:       return '\t';
        !           447:     case 'v':
        !           448:       return '\v';
        !           449:     case '\n':
        !           450:       return -2;
        !           451:     case 0:
        !           452:       (*string_ptr)--;
        !           453:       return 0;
        !           454:     case '^':
        !           455:       c = *(*string_ptr)++;
        !           456:       if (c == '\\')
        !           457:        c = parse_escape (string_ptr);
        !           458:       if (c == '?')
        !           459:        return 0177;
        !           460:       return (c & 0200) | (c & 037);
        !           461:       
        !           462:     case '0':
        !           463:     case '1':
        !           464:     case '2':
        !           465:     case '3':
        !           466:     case '4':
        !           467:     case '5':
        !           468:     case '6':
        !           469:     case '7':
        !           470:       {
        !           471:        register int i = c - '0';
        !           472:        register int count = 0;
        !           473:        while (++count < 3)
        !           474:          {
        !           475:            if ((c = *(*string_ptr)++) >= '0' && c <= '7')
        !           476:              {
        !           477:                i *= 8;
        !           478:                i += c - '0';
        !           479:              }
        !           480:            else
        !           481:              {
        !           482:                (*string_ptr)--;
        !           483:                break;
        !           484:              }
        !           485:          }
        !           486:        return i;
        !           487:       }
        !           488:     default:
        !           489:       return c;
        !           490:     }
        !           491: }
        !           492: 
        !           493: static
        !           494: yyerror (s)
        !           495:      char *s;
        !           496: {
        !           497:   error (s);
        !           498:   longjmp (parse_return_error, 1);
        !           499: }
        !           500: 
        !           501: /* This page contains the entry point to this file.  */
        !           502: 
        !           503: /* Parse STRING as an expression, and complain if this fails
        !           504:    to use up all of the contents of STRING.  */
        !           505: /* We do not support C comments.  They should be removed before
        !           506:    this function is called.  */
        !           507: 
        !           508: int
        !           509: parse_c_expression (string)
        !           510:      char *string;
        !           511: {
        !           512:   lexptr = string;
        !           513:   
        !           514:   if (lexptr == 0 || *lexptr == 0) {
        !           515:     error ("empty #if expression");
        !           516:     return 0;                  /* don't include the #if group */
        !           517:   }
        !           518: 
        !           519:   /* if there is some sort of scanning error, just return 0 and assume
        !           520:      the parsing routine has printed an error message somewhere.
        !           521:      there is surely a better thing to do than this.     */
        !           522:   if (setjmp(parse_return_error))
        !           523:     return 0;
        !           524: 
        !           525:   if (yyparse ())
        !           526:     return 0;                  /* actually this is never reached
        !           527:                                   the way things stand. */
        !           528:   if (*lexptr)
        !           529:     error ("Junk after end of expression.");
        !           530: 
        !           531:   return expression_value;     /* set by yyparse() */
        !           532: }
        !           533: 
        !           534: #ifdef TEST_EXP_READER
        !           535: /* main program, for testing purposes. */
        !           536: main()
        !           537: {
        !           538:   int n;
        !           539:   char buf[1024];
        !           540:   extern int yydebug;
        !           541: /*
        !           542:   yydebug = 1;
        !           543: */
        !           544:   initialize_random_junk ();
        !           545: 
        !           546:   for (;;) {
        !           547:     printf("enter expression: ");
        !           548:     n = 0;
        !           549:     while ((buf[n] = getchar()) != '\n')
        !           550:       n++;
        !           551:     buf[n] = '\0';
        !           552:     printf("parser returned %d\n", parse_c_expression(buf));
        !           553:   }
        !           554: }
        !           555: 
        !           556: /* table to tell if char can be part of a C identifier. */
        !           557: char is_idchar[256];
        !           558: /* table to tell if char can be first char of a c identifier. */
        !           559: char is_idstart[256];
        !           560: /* table to tell if c is horizontal space.  isspace() thinks that
        !           561:    newline is space; this is not a good idea for this program. */
        !           562: char is_hor_space[256];
        !           563: 
        !           564: /*
        !           565:  * initialize random junk in the hash table and maybe other places
        !           566:  */
        !           567: initialize_random_junk()
        !           568: {
        !           569:   register int i;
        !           570: 
        !           571:   /*
        !           572:    * Set up is_idchar and is_idstart tables.  These should be
        !           573:    * faster than saying (is_alpha(c) || c == '_'), etc.
        !           574:    * Must do set up these things before calling any routines tthat
        !           575:    * refer to them.
        !           576:    */
        !           577:   for (i = 'a'; i <= 'z'; i++) {
        !           578:     ++is_idchar[i - 'a' + 'A'];
        !           579:     ++is_idchar[i];
        !           580:     ++is_idstart[i - 'a' + 'A'];
        !           581:     ++is_idstart[i];
        !           582:   }
        !           583:   for (i = '0'; i <= '9'; i++)
        !           584:     ++is_idchar[i];
        !           585:   ++is_idchar['_'];
        !           586:   ++is_idstart['_'];
        !           587: #ifdef DOLLARS_IN_IDENTIFIERS
        !           588:   ++is_idchar['$'];
        !           589:   ++is_idstart['$'];
        !           590: #endif
        !           591: 
        !           592:   /* horizontal space table */
        !           593:   ++is_hor_space[' '];
        !           594:   ++is_hor_space['\t'];
        !           595: }
        !           596: 
        !           597: error (msg)
        !           598: {
        !           599:   printf("error: %s\n", msg);
        !           600: }
        !           601: #endif

unix.superglobalmegacorp.com

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