root/test/manual/etags/y-src/cccp.y

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. parse_number
  2. yylex
  3. parse_escape
  4. yyerror
  5. integer_overflow
  6. left_shift
  7. right_shift
  8. parse_c_expression
  9. main
  10. initialize_random_junk
  11. error
  12. warning
  13. lookup

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

/* [<][>][^][v][top][bottom][index][help] */