source: trunk/third/gcc/cexp.y @ 8834

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