Commit da51a478 by Richard Kenner

General code cleanup in the style of 1995-04-01 change.

Add prototypes for static functions.
Add parentheses suggested by `gcc -Wparentheses'.
Use `long' uniformly, instead of long, int, HOST_WIDE_INT mess.
(struct constant): Use `signedp' flag (with sign bit) instead of
`unsignedp' flag; it's a little more convenient.

(HAVE_STDLIB_H, STDC_HEADERS, LONG_MASK, __attribute__, PROTO,
VA_START, PRINTF_ALIST, PRINTF_DCL, PRINTF_PROTO, PRINTF_PROTO_1,
vfprintf, SIGNED, UNSIGNED): New symbols.
<stdlib.h>: Include if HAVE_STDLIB_H.
<string.h>: New include.
(HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT): Remove.
(yylex, yyerror, expression_value, parse_number,
initialize_random_junk): Now static.

(overflow_sum_sign): Renamed from possible_sum_sign, with an
extra arg SIGNEDP.
(parse_number): Inline strcmp when checking for "0x".
(yylex): Keep track of mask needed when decoding wide characters.
(parse_escape): New arg RESULT_MASK; use it instead of
assuming char width.
(yylex, parse_escape, parse_c_expression): Store all host
integers as long, not int or HOST_WIDE_INT.
(left_shift): No need to do signed left shifts separately.

These changes are for the test program (if TEST_EXP_READER):
(pedantic, traditional): Allocate storage.
(main): Set pedantic, traditional, yydebug depending on args.
(is_hor_space, warning, lookup): Change types and implementation
to match rest of program.
(pedwarn, check_assertion, xmalloc): New functions.

From-SVN: r11024
parent 2994a9ac
/* Parse C expressions for CCCP. /* Parse C expressions for CCCP.
Copyright (C) 1987, 1992, 1994, 1995 Free Software Foundation. Copyright (C) 1987, 1992, 1994, 1995, 1996 Free Software Foundation.
This program is free software; you can redistribute it and/or modify it This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the under the terms of the GNU General Public License as published by the
...@@ -29,8 +29,30 @@ Boston, MA 02111-1307, USA. ...@@ -29,8 +29,30 @@ Boston, MA 02111-1307, USA.
#include <setjmp.h> #include <setjmp.h>
/* #define YYDEBUG 1 */ /* #define YYDEBUG 1 */
/* The following symbols should be autoconfigured:
HAVE_STDLIB_H
STDC_HEADERS
In the mean time, we'll get by with approximations based
on existing GCC configuration symbols. */
#ifdef POSIX
# ifndef HAVE_STDLIB_H
# define HAVE_STDLIB_H 1
# endif
# ifndef STDC_HEADERS
# define STDC_HEADERS 1
# endif
#endif /* defined (POSIX) */
#if STDC_HEADERS
# include <string.h>
#endif
#if HAVE_STDLIB_H || defined (MULTIBYTE_CHARS)
# include <stdlib.h>
#endif
#ifdef MULTIBYTE_CHARS #ifdef MULTIBYTE_CHARS
#include <stdlib.h>
#include <locale.h> #include <locale.h>
#endif #endif
...@@ -60,27 +82,53 @@ struct arglist { ...@@ -60,27 +82,53 @@ struct arglist {
#endif #endif
#endif #endif
/* Find the largest host integer type and set its size and type. */ #define LONG_MASK(bits) ((bits) < HOST_BITS_PER_LONG ? ~(~0L << (bits)) : ~0L)
#ifndef HOST_BITS_PER_WIDE_INT #ifndef NULL_PTR
#define NULL_PTR ((GENERIC_PTR)0)
#endif
#if HOST_BITS_PER_LONG > HOST_BITS_PER_INT #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6)
#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG # define __attribute__(x)
#define HOST_WIDE_INT long
#else
#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
#define HOST_WIDE_INT int
#endif #endif
#ifndef PROTO
# if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
# define PROTO(ARGS) ARGS
# else
# define PROTO(ARGS) ()
# endif
#endif #endif
#ifndef NULL_PTR #if defined (__STDC__) && defined (HAVE_VPRINTF)
#define NULL_PTR ((GENERIC_PTR)0) # include <stdarg.h>
# define VA_START(va_list, var) va_start (va_list, var)
# define PRINTF_ALIST(msg) char *msg, ...
# define PRINTF_DCL(msg)
# define PRINTF_PROTO(ARGS, m, n) PROTO (ARGS) __attribute__ ((format (printf, m, n)))
#else
# include <varargs.h>
# define VA_START(va_list, var) va_start (va_list)
# define PRINTF_ALIST(msg) msg, va_alist
# define PRINTF_DCL(msg) char *msg; va_dcl
# define PRINTF_PROTO(ARGS, m, n) () __attribute__ ((format (printf, m, n)))
# define vfprintf(file, msg, args) \
{ \
char *a0 = va_arg(args, char *); \
char *a1 = va_arg(args, char *); \
char *a2 = va_arg(args, char *); \
char *a3 = va_arg(args, char *); \
fprintf (file, msg, a0, a1, a2, a3); \
}
#endif #endif
int yylex (); #define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2)
void yyerror ();
HOST_WIDE_INT expression_value; long parse_c_expression PROTO((char *));
static int yylex PROTO((void));
static void yyerror PROTO((char *)) __attribute__ ((noreturn));
static long expression_value;
static jmp_buf parse_return_error; static jmp_buf parse_return_error;
...@@ -94,8 +142,6 @@ static int skip_evaluation; ...@@ -94,8 +142,6 @@ static int skip_evaluation;
/* some external tables of character types */ /* some external tables of character types */
extern unsigned char is_idstart[], is_idchar[], is_hor_space[]; extern unsigned char is_idstart[], is_idchar[], is_hor_space[];
extern char *xmalloc ();
/* Flag for -pedantic. */ /* Flag for -pedantic. */
extern int pedantic; extern int pedantic;
...@@ -134,17 +180,38 @@ extern int traditional; ...@@ -134,17 +180,38 @@ extern int traditional;
#define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
#endif #endif
/* Yield nonzero if adding two numbers with A's and B's signs can yield a /* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow.
number with SUM's sign, where A, B, and SUM are all C integers. */ Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1.
#define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0) Suppose SIGNEDP is negative if the result is signed, zero if unsigned.
Then this yields nonzero if overflow occurred during the addition.
static void integer_overflow (); Overflow occurs if A and B have the same sign, but A and SUM differ in sign,
static long left_shift (); and SIGNEDP is negative.
static long right_shift (); Use `^' to test whether signs differ, and `< 0' to isolate the sign. */
#define overflow_sum_sign(a, b, sum, signedp) \
((~((a) ^ (b)) & ((a) ^ (sum)) & (signedp)) < 0)
struct constant;
GENERIC_PTR xmalloc PROTO((size_t));
long parse_escape PROTO((char **, long));
int check_assertion PROTO((U_CHAR *, int, int, struct arglist *));
struct hashnode *lookup PROTO((U_CHAR *, int, int));
void error PRINTF_PROTO_1((char *, ...));
void pedwarn PRINTF_PROTO_1((char *, ...));
void warning PRINTF_PROTO_1((char *, ...));
static int parse_number PROTO((int));
static long left_shift PROTO((struct constant *, unsigned long));
static long right_shift PROTO((struct constant *, unsigned long));
static void integer_overflow PROTO((void));
/* `signedp' values */
#define SIGNED (~0)
#define UNSIGNED 0
%} %}
%union { %union {
struct constant {long value; int unsignedp;} integer; struct constant {long value; int signedp;} integer;
struct name {U_CHAR *address; int length;} name; struct name {U_CHAR *address; int length;} name;
struct arglist *keywords; struct arglist *keywords;
} }
...@@ -188,45 +255,45 @@ exp1 : exp ...@@ -188,45 +255,45 @@ exp1 : exp
/* Expressions, not including the comma operator. */ /* Expressions, not including the comma operator. */
exp : '-' exp %prec UNARY exp : '-' exp %prec UNARY
{ $$.value = - $2.value; { $$.value = - $2.value;
if (($$.value & $2.value) < 0 && ! $2.unsignedp) $$.signedp = $2.signedp;
integer_overflow (); if (($$.value & $2.value & $$.signedp) < 0)
$$.unsignedp = $2.unsignedp; } integer_overflow (); }
| '!' exp %prec UNARY | '!' exp %prec UNARY
{ $$.value = ! $2.value; { $$.value = ! $2.value;
$$.unsignedp = 0; } $$.signedp = SIGNED; }
| '+' exp %prec UNARY | '+' exp %prec UNARY
{ $$ = $2; } { $$ = $2; }
| '~' exp %prec UNARY | '~' exp %prec UNARY
{ $$.value = ~ $2.value; { $$.value = ~ $2.value;
$$.unsignedp = $2.unsignedp; } $$.signedp = $2.signedp; }
| '#' NAME | '#' NAME
{ $$.value = check_assertion ($2.address, $2.length, { $$.value = check_assertion ($2.address, $2.length,
0, NULL_PTR); 0, NULL_PTR);
$$.unsignedp = 0; } $$.signedp = SIGNED; }
| '#' NAME | '#' NAME
{ keyword_parsing = 1; } { keyword_parsing = 1; }
'(' keywords ')' '(' keywords ')'
{ $$.value = check_assertion ($2.address, $2.length, { $$.value = check_assertion ($2.address, $2.length,
1, $5); 1, $5);
keyword_parsing = 0; keyword_parsing = 0;
$$.unsignedp = 0; } $$.signedp = SIGNED; }
| '(' exp1 ')' | '(' exp1 ')'
{ $$ = $2; } { $$ = $2; }
; ;
/* Binary operators in order of decreasing precedence. */ /* Binary operators in order of decreasing precedence. */
exp : exp '*' exp exp : exp '*' exp
{ $$.unsignedp = $1.unsignedp || $3.unsignedp; { $$.signedp = $1.signedp & $3.signedp;
if ($$.unsignedp) if ($$.signedp)
$$.value = (unsigned long) $1.value * $3.value;
else
{ {
$$.value = $1.value * $3.value; $$.value = $1.value * $3.value;
if ($1.value if ($1.value
&& ($$.value / $1.value != $3.value && ($$.value / $1.value != $3.value
|| ($$.value & $1.value & $3.value) < 0)) || ($$.value & $1.value & $3.value) < 0))
integer_overflow (); integer_overflow ();
} } }
else
$$.value = (unsigned long) $1.value * $3.value; }
| exp '/' exp | exp '/' exp
{ if ($3.value == 0) { if ($3.value == 0)
{ {
...@@ -234,15 +301,15 @@ exp : exp '*' exp ...@@ -234,15 +301,15 @@ exp : exp '*' exp
error ("division by zero in #if"); error ("division by zero in #if");
$3.value = 1; $3.value = 1;
} }
$$.unsignedp = $1.unsignedp || $3.unsignedp; $$.signedp = $1.signedp & $3.signedp;
if ($$.unsignedp) if ($$.signedp)
$$.value = (unsigned long) $1.value / $3.value;
else
{ {
$$.value = $1.value / $3.value; $$.value = $1.value / $3.value;
if (($$.value & $1.value & $3.value) < 0) if (($$.value & $1.value & $3.value) < 0)
integer_overflow (); integer_overflow ();
} } }
else
$$.value = (unsigned long) $1.value / $3.value; }
| exp '%' exp | exp '%' exp
{ if ($3.value == 0) { if ($3.value == 0)
{ {
...@@ -250,88 +317,86 @@ exp : exp '*' exp ...@@ -250,88 +317,86 @@ exp : exp '*' exp
error ("division by zero in #if"); error ("division by zero in #if");
$3.value = 1; $3.value = 1;
} }
$$.unsignedp = $1.unsignedp || $3.unsignedp; $$.signedp = $1.signedp & $3.signedp;
if ($$.unsignedp) if ($$.signedp)
$$.value = (unsigned long) $1.value % $3.value; $$.value = $1.value % $3.value;
else else
$$.value = $1.value % $3.value; } $$.value = (unsigned long) $1.value % $3.value; }
| exp '+' exp | exp '+' exp
{ $$.value = $1.value + $3.value; { $$.value = $1.value + $3.value;
$$.unsignedp = $1.unsignedp || $3.unsignedp; $$.signedp = $1.signedp & $3.signedp;
if (! $$.unsignedp if (overflow_sum_sign ($1.value, $3.value,
&& ! possible_sum_sign ($1.value, $3.value, $$.value, $$.signedp))
$$.value))
integer_overflow (); } integer_overflow (); }
| exp '-' exp | exp '-' exp
{ $$.value = $1.value - $3.value; { $$.value = $1.value - $3.value;
$$.unsignedp = $1.unsignedp || $3.unsignedp; $$.signedp = $1.signedp & $3.signedp;
if (! $$.unsignedp if (overflow_sum_sign ($$.value, $3.value,
&& ! possible_sum_sign ($$.value, $3.value, $1.value, $$.signedp))
$1.value))
integer_overflow (); } integer_overflow (); }
| exp LSH exp | exp LSH exp
{ $$.unsignedp = $1.unsignedp; { $$.signedp = $1.signedp;
if ($3.value < 0 && ! $3.unsignedp) if (($3.value & $3.signedp) < 0)
$$.value = right_shift (&$1, -$3.value); $$.value = right_shift (&$1, -$3.value);
else else
$$.value = left_shift (&$1, $3.value); } $$.value = left_shift (&$1, $3.value); }
| exp RSH exp | exp RSH exp
{ $$.unsignedp = $1.unsignedp; { $$.signedp = $1.signedp;
if ($3.value < 0 && ! $3.unsignedp) if (($3.value & $3.signedp) < 0)
$$.value = left_shift (&$1, -$3.value); $$.value = left_shift (&$1, -$3.value);
else else
$$.value = right_shift (&$1, $3.value); } $$.value = right_shift (&$1, $3.value); }
| exp EQUAL exp | exp EQUAL exp
{ $$.value = ($1.value == $3.value); { $$.value = ($1.value == $3.value);
$$.unsignedp = 0; } $$.signedp = SIGNED; }
| exp NOTEQUAL exp | exp NOTEQUAL exp
{ $$.value = ($1.value != $3.value); { $$.value = ($1.value != $3.value);
$$.unsignedp = 0; } $$.signedp = SIGNED; }
| exp LEQ exp | exp LEQ exp
{ $$.unsignedp = 0; { $$.signedp = SIGNED;
if ($1.unsignedp || $3.unsignedp) if ($1.signedp & $3.signedp)
$$.value = (unsigned long) $1.value <= $3.value; $$.value = $1.value <= $3.value;
else else
$$.value = $1.value <= $3.value; } $$.value = (unsigned long) $1.value <= $3.value; }
| exp GEQ exp | exp GEQ exp
{ $$.unsignedp = 0; { $$.signedp = SIGNED;
if ($1.unsignedp || $3.unsignedp) if ($1.signedp & $3.signedp)
$$.value = (unsigned long) $1.value >= $3.value; $$.value = $1.value >= $3.value;
else else
$$.value = $1.value >= $3.value; } $$.value = (unsigned long) $1.value >= $3.value; }
| exp '<' exp | exp '<' exp
{ $$.unsignedp = 0; { $$.signedp = SIGNED;
if ($1.unsignedp || $3.unsignedp) if ($1.signedp & $3.signedp)
$$.value = (unsigned long) $1.value < $3.value; $$.value = $1.value < $3.value;
else else
$$.value = $1.value < $3.value; } $$.value = (unsigned long) $1.value < $3.value; }
| exp '>' exp | exp '>' exp
{ $$.unsignedp = 0; { $$.signedp = SIGNED;
if ($1.unsignedp || $3.unsignedp) if ($1.signedp & $3.signedp)
$$.value = (unsigned long) $1.value > $3.value; $$.value = $1.value > $3.value;
else else
$$.value = $1.value > $3.value; } $$.value = (unsigned long) $1.value > $3.value; }
| exp '&' exp | exp '&' exp
{ $$.value = $1.value & $3.value; { $$.value = $1.value & $3.value;
$$.unsignedp = $1.unsignedp || $3.unsignedp; } $$.signedp = $1.signedp & $3.signedp; }
| exp '^' exp | exp '^' exp
{ $$.value = $1.value ^ $3.value; { $$.value = $1.value ^ $3.value;
$$.unsignedp = $1.unsignedp || $3.unsignedp; } $$.signedp = $1.signedp & $3.signedp; }
| exp '|' exp | exp '|' exp
{ $$.value = $1.value | $3.value; { $$.value = $1.value | $3.value;
$$.unsignedp = $1.unsignedp || $3.unsignedp; } $$.signedp = $1.signedp & $3.signedp; }
| exp AND | exp AND
{ skip_evaluation += !$1.value; } { skip_evaluation += !$1.value; }
exp exp
{ skip_evaluation -= !$1.value; { skip_evaluation -= !$1.value;
$$.value = ($1.value && $4.value); $$.value = ($1.value && $4.value);
$$.unsignedp = 0; } $$.signedp = SIGNED; }
| exp OR | exp OR
{ skip_evaluation += !!$1.value; } { skip_evaluation += !!$1.value; }
exp exp
{ skip_evaluation -= !!$1.value; { skip_evaluation -= !!$1.value;
$$.value = ($1.value || $4.value); $$.value = ($1.value || $4.value);
$$.unsignedp = 0; } $$.signedp = SIGNED; }
| exp '?' | exp '?'
{ skip_evaluation += !$1.value; } { skip_evaluation += !$1.value; }
exp ':' exp ':'
...@@ -339,14 +404,14 @@ exp : exp '*' exp ...@@ -339,14 +404,14 @@ exp : exp '*' exp
exp exp
{ skip_evaluation -= !!$1.value; { skip_evaluation -= !!$1.value;
$$.value = $1.value ? $4.value : $7.value; $$.value = $1.value ? $4.value : $7.value;
$$.unsignedp = $4.unsignedp || $7.unsignedp; } $$.signedp = $4.signedp & $7.signedp; }
| INT | INT
{ $$ = yylval.integer; } { $$ = yylval.integer; }
| CHAR | CHAR
{ $$ = yylval.integer; } { $$ = yylval.integer; }
| NAME | NAME
{ $$.value = 0; { $$.value = 0;
$$.unsignedp = 0; } $$.signedp = SIGNED; }
; ;
keywords : keywords :
...@@ -383,7 +448,7 @@ static char *lexptr; ...@@ -383,7 +448,7 @@ static char *lexptr;
/* maybe needs to actually deal with floating point numbers */ /* maybe needs to actually deal with floating point numbers */
int static int
parse_number (olen) parse_number (olen)
int olen; int olen;
{ {
...@@ -396,15 +461,16 @@ parse_number (olen) ...@@ -396,15 +461,16 @@ parse_number (olen)
register int digit, largest_digit = 0; register int digit, largest_digit = 0;
int spec_long = 0; int spec_long = 0;
yylval.integer.unsignedp = 0; yylval.integer.signedp = SIGNED;
if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) { if (*p == '0') {
p += 2;
base = 16;
len -= 2;
}
else if (*p == '0')
base = 8; base = 8;
if (len >= 3 && (p[1] == 'x' || p[1] == 'X')) {
p += 2;
base = 16;
len -= 2;
}
}
ULONG_MAX_over_base = (unsigned long) -1 / base; ULONG_MAX_over_base = (unsigned long) -1 / base;
...@@ -428,9 +494,9 @@ parse_number (olen) ...@@ -428,9 +494,9 @@ parse_number (olen)
} }
else if (c == 'u' || c == 'U') else if (c == 'u' || c == 'U')
{ {
if (yylval.integer.unsignedp) if (! yylval.integer.signedp)
yyerror ("two `u's in integer constant"); yyerror ("two `u's in integer constant");
yylval.integer.unsignedp = 1; yylval.integer.signedp = UNSIGNED;
} }
else { else {
if (c == '.' || c == 'e' || c == 'E') if (c == '.' || c == 'e' || c == 'E')
...@@ -453,7 +519,7 @@ parse_number (olen) ...@@ -453,7 +519,7 @@ parse_number (olen)
if (largest_digit < digit) if (largest_digit < digit)
largest_digit = digit; largest_digit = digit;
nd = n * base + digit; nd = n * base + digit;
overflow |= ULONG_MAX_over_base < n | nd < n; overflow |= (ULONG_MAX_over_base < n) | (nd < n);
n = nd; n = nd;
} }
...@@ -464,11 +530,11 @@ parse_number (olen) ...@@ -464,11 +530,11 @@ parse_number (olen)
warning ("integer constant out of range"); warning ("integer constant out of range");
/* If too big to be signed, consider it unsigned. */ /* If too big to be signed, consider it unsigned. */
if ((long) n < 0 && ! yylval.integer.unsignedp) if (((long) n & yylval.integer.signedp) < 0)
{ {
if (base == 10) if (base == 10)
warning ("integer constant is so large that it is unsigned"); warning ("integer constant is so large that it is unsigned");
yylval.integer.unsignedp = 1; yylval.integer.signedp = UNSIGNED;
} }
lexptr = p; lexptr = p;
...@@ -497,7 +563,7 @@ static struct token tokentab2[] = { ...@@ -497,7 +563,7 @@ static struct token tokentab2[] = {
/* Read one token, getting characters through lexptr. */ /* Read one token, getting characters through lexptr. */
int static int
yylex () yylex ()
{ {
register int c; register int c;
...@@ -505,6 +571,7 @@ yylex () ...@@ -505,6 +571,7 @@ yylex ()
register unsigned char *tokstart; register unsigned char *tokstart;
register struct token *toktab; register struct token *toktab;
int wide_flag; int wide_flag;
long mask;
retry: retry:
...@@ -540,18 +607,21 @@ yylex () ...@@ -540,18 +607,21 @@ yylex ()
{ {
lexptr++; lexptr++;
wide_flag = 1; wide_flag = 1;
mask = LONG_MASK (MAX_WCHAR_TYPE_SIZE);
goto char_constant; goto char_constant;
} }
if (lexptr[1] == '"') if (lexptr[1] == '"')
{ {
lexptr++; lexptr++;
wide_flag = 1; wide_flag = 1;
mask = LONG_MASK (MAX_WCHAR_TYPE_SIZE);
goto string_constant; goto string_constant;
} }
break; break;
case '\'': case '\'':
wide_flag = 0; wide_flag = 0;
mask = LONG_MASK (MAX_CHAR_TYPE_SIZE);
char_constant: char_constant:
lexptr++; lexptr++;
if (keyword_parsing) { if (keyword_parsing) {
...@@ -559,7 +629,7 @@ yylex () ...@@ -559,7 +629,7 @@ yylex ()
while (1) { while (1) {
c = *lexptr++; c = *lexptr++;
if (c == '\\') if (c == '\\')
c = parse_escape (&lexptr); c = parse_escape (&lexptr, mask);
else if (c == '\'') else if (c == '\'')
break; break;
} }
...@@ -572,7 +642,7 @@ yylex () ...@@ -572,7 +642,7 @@ yylex ()
handles multicharacter constants and wide characters. handles multicharacter constants and wide characters.
It is mostly copied from c-lex.c. */ It is mostly copied from c-lex.c. */
{ {
register int result = 0; register long result = 0;
register num_chars = 0; register num_chars = 0;
unsigned width = MAX_CHAR_TYPE_SIZE; unsigned width = MAX_CHAR_TYPE_SIZE;
int max_chars; int max_chars;
...@@ -601,19 +671,16 @@ yylex () ...@@ -601,19 +671,16 @@ yylex ()
if (c == '\\') if (c == '\\')
{ {
c = parse_escape (&lexptr); c = parse_escape (&lexptr, mask);
if (width < HOST_BITS_PER_INT
&& (unsigned) c >= (1 << width))
pedwarn ("escape sequence out of range for character");
} }
num_chars++; num_chars++;
/* Merge character into result; ignore excess chars. */ /* Merge character into result; ignore excess chars. */
if (num_chars < max_chars + 1) if (num_chars <= max_chars)
{ {
if (width < HOST_BITS_PER_INT) if (width < HOST_BITS_PER_LONG)
result = (result << width) | (c & ((1 << width) - 1)); result = (result << width) | c;
else else
result = c; result = c;
token_buffer[num_chars - 1] = c; token_buffer[num_chars - 1] = c;
...@@ -642,10 +709,10 @@ yylex () ...@@ -642,10 +709,10 @@ yylex ()
if (lookup ("__CHAR_UNSIGNED__", sizeof ("__CHAR_UNSIGNED__")-1, -1) if (lookup ("__CHAR_UNSIGNED__", sizeof ("__CHAR_UNSIGNED__")-1, -1)
|| ((result >> (num_bits - 1)) & 1) == 0) || ((result >> (num_bits - 1)) & 1) == 0)
yylval.integer.value yylval.integer.value
= result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits)); = result & (~ (unsigned long) 0 >> (HOST_BITS_PER_LONG - num_bits));
else else
yylval.integer.value yylval.integer.value
= result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits)); = result | ~(~ (unsigned long) 0 >> (HOST_BITS_PER_LONG - num_bits));
} }
else else
{ {
...@@ -670,7 +737,7 @@ yylex () ...@@ -670,7 +737,7 @@ yylex ()
} }
/* This is always a signed type. */ /* This is always a signed type. */
yylval.integer.unsignedp = 0; yylval.integer.signedp = SIGNED;
return CHAR; return CHAR;
...@@ -707,6 +774,7 @@ yylex () ...@@ -707,6 +774,7 @@ yylex ()
return c; return c;
case '"': case '"':
mask = LONG_MASK (MAX_CHAR_TYPE_SIZE);
string_constant: string_constant:
if (keyword_parsing) { if (keyword_parsing) {
char *start_ptr = lexptr; char *start_ptr = lexptr;
...@@ -714,7 +782,7 @@ yylex () ...@@ -714,7 +782,7 @@ yylex ()
while (1) { while (1) {
c = *lexptr++; c = *lexptr++;
if (c == '\\') if (c == '\\')
c = parse_escape (&lexptr); c = parse_escape (&lexptr, mask);
else if (c == '"') else if (c == '"')
break; break;
} }
...@@ -772,6 +840,9 @@ yylex () ...@@ -772,6 +840,9 @@ yylex ()
is updated past the characters we use. The value of the is updated past the characters we use. The value of the
escape sequence is returned. escape sequence is returned.
RESULT_MASK is used to mask out the result;
an error is reported if bits are lost thereby.
A negative value means the sequence \ newline was seen, A negative value means the sequence \ newline was seen,
which is supposed to be equivalent to nothing at all. which is supposed to be equivalent to nothing at all.
...@@ -781,9 +852,10 @@ yylex () ...@@ -781,9 +852,10 @@ yylex ()
If \ is followed by 000, we return 0 and leave the string pointer If \ is followed by 000, we return 0 and leave the string pointer
after the zeros. A value of 0 does not mean end of string. */ after the zeros. A value of 0 does not mean end of string. */
int long
parse_escape (string_ptr) parse_escape (string_ptr, result_mask)
char **string_ptr; char **string_ptr;
long result_mask;
{ {
register int c = *(*string_ptr)++; register int c = *(*string_ptr)++;
switch (c) switch (c)
...@@ -822,7 +894,7 @@ parse_escape (string_ptr) ...@@ -822,7 +894,7 @@ parse_escape (string_ptr)
case '6': case '6':
case '7': case '7':
{ {
register int i = c - '0'; register long i = c - '0';
register int count = 0; register int count = 0;
while (++count < 3) while (++count < 3)
{ {
...@@ -835,16 +907,17 @@ parse_escape (string_ptr) ...@@ -835,16 +907,17 @@ parse_escape (string_ptr)
break; break;
} }
} }
if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0) if (i != (i & result_mask))
{ {
i &= (1 << MAX_CHAR_TYPE_SIZE) - 1; i &= result_mask;
warning ("octal character constant does not fit in a byte"); pedwarn ("octal escape sequence out of range");
} }
return i; return i;
} }
case 'x': case 'x':
{ {
register unsigned i = 0, overflow = 0, digits_found = 0, digit; register unsigned long i = 0, overflow = 0;
register int digits_found = 0, digit;
for (;;) for (;;)
{ {
c = *(*string_ptr)++; c = *(*string_ptr)++;
...@@ -865,10 +938,10 @@ parse_escape (string_ptr) ...@@ -865,10 +938,10 @@ parse_escape (string_ptr)
} }
if (!digits_found) if (!digits_found)
yyerror ("\\x used with no following hex digits"); yyerror ("\\x used with no following hex digits");
if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1))) if (overflow | (i != (i & result_mask)))
{ {
i &= (1 << BITS_PER_UNIT) - 1; i &= result_mask;
warning ("hex character constant does not fit in a byte"); pedwarn ("hex escape sequence out of range");
} }
return i; return i;
} }
...@@ -877,11 +950,11 @@ parse_escape (string_ptr) ...@@ -877,11 +950,11 @@ parse_escape (string_ptr)
} }
} }
void static void
yyerror (s) yyerror (s)
char *s; char *s;
{ {
error (s); error ("%s", s);
skip_evaluation = 0; skip_evaluation = 0;
longjmp (parse_return_error, 1); longjmp (parse_return_error, 1);
} }
...@@ -903,10 +976,8 @@ left_shift (a, b) ...@@ -903,10 +976,8 @@ left_shift (a, b)
interpretation ruling is needed. */ interpretation ruling is needed. */
if (b >= HOST_BITS_PER_LONG) if (b >= HOST_BITS_PER_LONG)
return 0; return 0;
else if (a->unsignedp)
return (unsigned long) a->value << b;
else else
return a->value << b; return (unsigned long) a->value << b;
} }
static long static long
...@@ -915,11 +986,11 @@ right_shift (a, b) ...@@ -915,11 +986,11 @@ right_shift (a, b)
unsigned long b; unsigned long b;
{ {
if (b >= HOST_BITS_PER_LONG) if (b >= HOST_BITS_PER_LONG)
return a->unsignedp ? 0 : a->value >> (HOST_BITS_PER_LONG - 1); return a->signedp ? a->value >> (HOST_BITS_PER_LONG - 1) : 0;
else if (a->unsignedp) else if (a->signedp)
return (unsigned long) a->value >> b;
else
return a->value >> b; return a->value >> b;
else
return (unsigned long) a->value >> b;
} }
/* This page contains the entry point to this file. */ /* This page contains the entry point to this file. */
...@@ -931,7 +1002,7 @@ right_shift (a, b) ...@@ -931,7 +1002,7 @@ right_shift (a, b)
/* We do not support C comments. They should be removed before /* We do not support C comments. They should be removed before
this function is called. */ this function is called. */
HOST_WIDE_INT long
parse_c_expression (string) parse_c_expression (string)
char *string; char *string;
{ {
...@@ -958,18 +1029,31 @@ parse_c_expression (string) ...@@ -958,18 +1029,31 @@ parse_c_expression (string)
} }
#ifdef TEST_EXP_READER #ifdef TEST_EXP_READER
#if YYDEBUG
extern int yydebug; extern int yydebug;
#endif
int pedantic;
int traditional;
int main PROTO((int, char **));
static void initialize_random_junk PROTO((void));
/* Main program for testing purposes. */ /* Main program for testing purposes. */
int int
main () main (argc, argv)
int argc;
char **argv;
{ {
int n, c; int n, c;
char buf[1024]; char buf[1024];
/* pedantic = 1 < argc;
yydebug = 1; traditional = 2 < argc;
*/ #if YYDEBUG
yydebug = 3 < argc;
#endif
initialize_random_junk (); initialize_random_junk ();
for (;;) { for (;;) {
...@@ -991,11 +1075,12 @@ unsigned char is_idchar[256]; ...@@ -991,11 +1075,12 @@ unsigned char is_idchar[256];
unsigned char is_idstart[256]; unsigned char is_idstart[256];
/* table to tell if c is horizontal space. isspace () thinks that /* table to tell if c is horizontal space. isspace () thinks that
newline is space; this is not a good idea for this program. */ newline is space; this is not a good idea for this program. */
char is_hor_space[256]; unsigned char is_hor_space[256];
/* /*
* initialize random junk in the hash table and maybe other places * initialize random junk in the hash table and maybe other places
*/ */
static void
initialize_random_junk () initialize_random_junk ()
{ {
register int i; register int i;
...@@ -1026,22 +1111,68 @@ initialize_random_junk () ...@@ -1026,22 +1111,68 @@ initialize_random_junk ()
++is_hor_space['\t']; ++is_hor_space['\t'];
} }
error (msg) void
error (PRINTF_ALIST (msg))
PRINTF_DCL (msg)
{ {
printf ("error: %s\n", msg); va_list args;
VA_START (args, msg);
fprintf (stderr, "error: ");
vfprintf (stderr, msg, args);
fprintf (stderr, "\n");
va_end (args);
} }
warning (msg) void
pedwarn (PRINTF_ALIST (msg))
PRINTF_DCL (msg)
{
va_list args;
VA_START (args, msg);
fprintf (stderr, "pedwarn: ");
vfprintf (stderr, msg, args);
fprintf (stderr, "\n");
va_end (args);
}
void
warning (PRINTF_ALIST (msg))
PRINTF_DCL (msg)
{ {
printf ("warning: %s\n", msg); va_list args;
VA_START (args, msg);
fprintf (stderr, "warning: ");
vfprintf (stderr, msg, args);
fprintf (stderr, "\n");
va_end (args);
}
int
check_assertion (name, sym_length, tokens_specified, tokens)
U_CHAR *name;
int sym_length;
int tokens_specified;
struct arglist *tokens;
{
return 0;
} }
struct hashnode * struct hashnode *
lookup (name, len, hash) lookup (name, len, hash)
char *name; U_CHAR *name;
int len; int len;
int hash; int hash;
{ {
return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1); return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1);
} }
GENERIC_PTR
xmalloc (size)
size_t size;
{
return (GENERIC_PTR) malloc (size);
}
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment