xref: /386bsd/usr/src/usr.bin/gcc/cpp/cexp.y (revision a2142627)
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
parse_number(olen)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
yylex()459 yylex ()
460 {
461   register int c;
462   register int namelen;
463   register char *tokstart;
464   register struct token *toktab;
465   int wide_flag;
466 
467  retry:
468 
469   tokstart = 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 = (U_CHAR *) 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 = (U_CHAR *) 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 = (U_CHAR *) 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
parse_escape(string_ptr)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       return 033;
752     case 'f':
753       return TARGET_FF;
754     case 'n':
755       return TARGET_NEWLINE;
756     case 'r':
757       return TARGET_CR;
758     case 't':
759       return TARGET_TAB;
760     case 'v':
761       return TARGET_VT;
762     case '\n':
763       return -2;
764     case 0:
765       (*string_ptr)--;
766       return 0;
767     case '^':
768       c = *(*string_ptr)++;
769       if (c == '\\')
770 	c = parse_escape (string_ptr);
771       if (c == '?')
772 	return 0177;
773       return (c & 0200) | (c & 037);
774 
775     case '0':
776     case '1':
777     case '2':
778     case '3':
779     case '4':
780     case '5':
781     case '6':
782     case '7':
783       {
784 	register int i = c - '0';
785 	register int count = 0;
786 	while (++count < 3)
787 	  {
788 	    c = *(*string_ptr)++;
789 	    if (c >= '0' && c <= '7')
790 	      i = (i << 3) + c - '0';
791 	    else
792 	      {
793 		(*string_ptr)--;
794 		break;
795 	      }
796 	  }
797 	if ((i & ~((1 << CHAR_TYPE_SIZE) - 1)) != 0)
798 	  {
799 	    i &= (1 << CHAR_TYPE_SIZE) - 1;
800 	    warning ("octal character constant does not fit in a byte");
801 	  }
802 	return i;
803       }
804     case 'x':
805       {
806 	register unsigned i = 0, overflow = 0, digits_found = 0, digit;
807 	for (;;)
808 	  {
809 	    c = *(*string_ptr)++;
810 	    if (c >= '0' && c <= '9')
811 	      digit = c - '0';
812 	    else if (c >= 'a' && c <= 'f')
813 	      digit = c - 'a' + 10;
814 	    else if (c >= 'A' && c <= 'F')
815 	      digit = c - 'A' + 10;
816 	    else
817 	      {
818 		(*string_ptr)--;
819 		break;
820 	      }
821 	    overflow |= i ^ (i << 4 >> 4);
822 	    i = (i << 4) + digit;
823 	    digits_found = 1;
824 	  }
825 	if (!digits_found)
826 	  yyerror ("\\x used with no following hex digits");
827 	if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1)))
828 	  {
829 	    i &= (1 << BITS_PER_UNIT) - 1;
830 	    warning ("hex character constant does not fit in a byte");
831 	  }
832 	return i;
833       }
834     default:
835       return c;
836     }
837 }
838 
839 void
yyerror(s)840 yyerror (s)
841      char *s;
842 {
843   error (s);
844   longjmp (parse_return_error, 1);
845 }
846 
847 static void
integer_overflow()848 integer_overflow ()
849 {
850   if (pedantic)
851     pedwarn ("integer overflow in preprocessor expression");
852 }
853 
854 static long
left_shift(a,b)855 left_shift (a, b)
856      struct constant *a;
857      unsigned long b;
858 {
859   if (b >= HOST_BITS_PER_LONG)
860     {
861       if (! a->unsignedp && a->value != 0)
862 	integer_overflow ();
863       return 0;
864     }
865   else if (a->unsignedp)
866     return (unsigned long) a->value << b;
867   else
868     {
869       long l = a->value << b;
870       if (l >> b != a->value)
871 	integer_overflow ();
872       return l;
873     }
874 }
875 
876 static long
right_shift(a,b)877 right_shift (a, b)
878      struct constant *a;
879      unsigned long b;
880 {
881   if (b >= HOST_BITS_PER_LONG)
882     return a->unsignedp ? 0 : a->value >> (HOST_BITS_PER_LONG - 1);
883   else if (a->unsignedp)
884     return (unsigned long) a->value >> b;
885   else
886     return a->value >> b;
887 }
888 
889 /* This page contains the entry point to this file.  */
890 
891 /* Parse STRING as an expression, and complain if this fails
892    to use up all of the contents of STRING.  */
893 /* We do not support C comments.  They should be removed before
894    this function is called.  */
895 
896 int
parse_c_expression(string)897 parse_c_expression (string)
898      char *string;
899 {
900   lexptr = string;
901 
902   if (lexptr == 0 || *lexptr == 0) {
903     error ("empty #if expression");
904     return 0;			/* don't include the #if group */
905   }
906 
907   /* if there is some sort of scanning error, just return 0 and assume
908      the parsing routine has printed an error message somewhere.
909      there is surely a better thing to do than this.     */
910   if (setjmp (parse_return_error))
911     return 0;
912 
913   if (yyparse ())
914     return 0;			/* actually this is never reached
915 				   the way things stand. */
916   if (*lexptr)
917     error ("Junk after end of expression.");
918 
919   return expression_value;	/* set by yyparse () */
920 }
921 
922 #ifdef TEST_EXP_READER
923 extern int yydebug;
924 
925 /* Main program for testing purposes.  */
926 int
main()927 main ()
928 {
929   int n, c;
930   char buf[1024];
931 
932 /*
933   yydebug = 1;
934 */
935   initialize_random_junk ();
936 
937   for (;;) {
938     printf ("enter expression: ");
939     n = 0;
940     while ((buf[n] = getchar ()) != '\n' && buf[n] != EOF)
941       n++;
942     if (buf[n] == EOF)
943       break;
944     buf[n] = '\0';
945     printf ("parser returned %d\n", parse_c_expression (buf));
946   }
947 
948   return 0;
949 }
950 
951 /* table to tell if char can be part of a C identifier. */
952 unsigned char is_idchar[256];
953 /* table to tell if char can be first char of a c identifier. */
954 unsigned char is_idstart[256];
955 /* table to tell if c is horizontal space.  isspace () thinks that
956    newline is space; this is not a good idea for this program. */
957 char is_hor_space[256];
958 
959 /*
960  * initialize random junk in the hash table and maybe other places
961  */
initialize_random_junk()962 initialize_random_junk ()
963 {
964   register int i;
965 
966   /*
967    * Set up is_idchar and is_idstart tables.  These should be
968    * faster than saying (is_alpha (c) || c == '_'), etc.
969    * Must do set up these things before calling any routines tthat
970    * refer to them.
971    */
972   for (i = 'a'; i <= 'z'; i++) {
973     ++is_idchar[i - 'a' + 'A'];
974     ++is_idchar[i];
975     ++is_idstart[i - 'a' + 'A'];
976     ++is_idstart[i];
977   }
978   for (i = '0'; i <= '9'; i++)
979     ++is_idchar[i];
980   ++is_idchar['_'];
981   ++is_idstart['_'];
982 #if DOLLARS_IN_IDENTIFIERS
983   ++is_idchar['$'];
984   ++is_idstart['$'];
985 #endif
986 
987   /* horizontal space table */
988   ++is_hor_space[' '];
989   ++is_hor_space['\t'];
990 }
991 
error(msg)992 error (msg)
993 {
994   printf ("error: %s\n", msg);
995 }
996 
warning(msg)997 warning (msg)
998 {
999   printf ("warning: %s\n", msg);
1000 }
1001 
1002 struct hashnode *
lookup(name,len,hash)1003 lookup (name, len, hash)
1004      char *name;
1005      int len;
1006      int hash;
1007 {
1008   return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1);
1009 }
1010 #endif
1011