/* Lexical analyzer for C and Objective C.
- Copyright (C) 1987, 88, 89, 92, 94-96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92, 94-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
Boston, MA 02111-1307, USA. */
#include "config.h"
-
-#include <stdio.h>
-#include <errno.h>
+#include "system.h"
#include <setjmp.h>
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
#include "rtl.h"
#include "tree.h"
#include "input.h"
+#include "output.h"
#include "c-lex.h"
#include "c-tree.h"
#include "flags.h"
#include "c-parse.h"
#include "c-pragma.h"
-
-#include <ctype.h>
+#include "toplev.h"
/* MULTIBYTE_CHARS support only works for native compilers.
??? Ideally what we want is to model widechar support after
#endif
#ifdef MULTIBYTE_CHARS
-#include <stdlib.h>
#include <locale.h>
#endif
-#ifndef errno
-extern int errno;
-#endif
-
#if USE_CPPLIB
#include "cpplib.h"
-cpp_reader parse_in;
-cpp_options parse_options;
-static enum cpp_token cpp_token;
+extern cpp_reader parse_in;
+extern cpp_options parse_options;
+#else
+/* Stream for reading from the input file. */
+FILE *finput;
#endif
/* The elements of `ridpointers' are identifier nodes
#define YYDEBUG 1
#if USE_CPPLIB
-static unsigned char *yy_cur, *yy_lim;
-
-int
-yy_get_token ()
-{
- for (;;)
- {
- parse_in.limit = parse_in.token_buffer;
- cpp_token = cpp_get_token (&parse_in);
- if (cpp_token == CPP_EOF)
- return -1;
- yy_lim = CPP_PWRITTEN (&parse_in);
- yy_cur = parse_in.token_buffer;
- if (yy_cur < yy_lim)
- return *yy_cur++;
- }
-}
-
+extern unsigned char *yy_cur, *yy_lim;
+
+extern int yy_get_token ();
+
#define GETC() (yy_cur < yy_lim ? *yy_cur++ : yy_get_token ())
#define UNGETC(c) ((c), yy_cur--)
#else
int doing_objc_thang;
-extern tree is_class_name ();
-
extern int yydebug;
/* File used for outputting assembler code. */
#ifdef HANDLE_SYSV_PRAGMA
static int handle_sysv_pragma PROTO((int));
#endif /* HANDLE_SYSV_PRAGMA */
+static int whitespace_cr PROTO((int));
static int skip_white_space PROTO((int));
+static int skip_white_space_on_line PROTO((void));
static char *extend_token_buffer PROTO((char *));
static int readescape PROTO((int *));
int check_newline ();
wordlist[i].name = "oneway";
}
\f
-#if USE_CPPLIB
-void
+char *
init_parse (filename)
char *filename;
{
+#if !USE_CPPLIB
+ /* Open input file. */
+ if (filename == 0 || !strcmp (filename, "-"))
+ {
+ finput = stdin;
+ filename = "stdin";
+ }
+ else
+ finput = fopen (filename, "r");
+ if (finput == 0)
+ pfatal_with_name (filename);
+
+#ifdef IO_BUFFER_SIZE
+ setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
+#endif
+#endif /* !USE_CPPLIB */
+
init_lex ();
+
+#if USE_CPPLIB
yy_cur = "\n";
yy_lim = yy_cur+1;
parse_in.show_column = 1;
if (! cpp_start_read (&parse_in, filename))
abort ();
+#endif
+
+ return filename;
}
void
finish_parse ()
{
+#if USE_CPPLIB
cpp_finish (&parse_in);
-}
+#else
+ fclose (finput);
#endif
+}
void
init_lex ()
if (TREE_CODE (t) == INTEGER_CST)
fprintf (file,
#if HOST_BITS_PER_WIDE_INT == 64
-#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+ " 0x%x%016x",
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
" 0x%lx%016lx",
#else
- " 0x%x%016x",
+ " 0x%llx%016llx",
+#endif
#endif
#else
#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
\f
/* Iff C is a carriage return, warn about it - if appropriate -
and return nonzero. */
-int
+static int
whitespace_cr (c)
int c;
{
return token_buffer + offset;
}
\f
-#if !USE_CPPLIB
-#define GET_DIRECTIVE_LINE() get_directive_line (finput)
-#else /* USE_CPPLIB */
-/* Read the rest of a #-directive from input stream FINPUT.
- In normal use, the directive name and the white space after it
- have already been read, so they won't be included in the result.
- We allow for the fact that the directive line may contain
- a newline embedded within a character or string literal which forms
- a part of the directive.
-
- The value is a string in a reusable buffer. It remains valid
- only until the next time this function is called. */
-
-static char *
-GET_DIRECTIVE_LINE ()
-{
- static char *directive_buffer = NULL;
- static unsigned buffer_length = 0;
- register char *p;
- register char *buffer_limit;
- register int looking_for = 0;
- register int char_escaped = 0;
-
- if (buffer_length == 0)
- {
- directive_buffer = (char *)xmalloc (128);
- buffer_length = 128;
- }
-
- buffer_limit = &directive_buffer[buffer_length];
-
- for (p = directive_buffer; ; )
- {
- int c;
-
- /* Make buffer bigger if it is full. */
- if (p >= buffer_limit)
- {
- register unsigned bytes_used = (p - directive_buffer);
-
- buffer_length *= 2;
- directive_buffer
- = (char *)xrealloc (directive_buffer, buffer_length);
- p = &directive_buffer[bytes_used];
- buffer_limit = &directive_buffer[buffer_length];
- }
-
- c = GETC ();
-
- /* Discard initial whitespace. */
- if ((c == ' ' || c == '\t') && p == directive_buffer)
- continue;
-
- /* Detect the end of the directive. */
- if (c == '\n' && looking_for == 0)
- {
- UNGETC (c);
- c = '\0';
- }
-
- *p++ = c;
-
- if (c == 0)
- return directive_buffer;
-
- /* Handle string and character constant syntax. */
- if (looking_for)
- {
- if (looking_for == c && !char_escaped)
- looking_for = 0; /* Found terminator... stop looking. */
- }
- else
- if (c == '\'' || c == '"')
- looking_for = c; /* Don't stop buffering until we see another
- another one of these (or an EOF). */
-
- /* Handle backslash. */
- char_escaped = (c == '\\' && ! char_escaped);
- }
-}
-#endif /* USE_CPPLIB */
-\f
/* At the beginning of a line, increment the line number
and process any #-directive on this line.
If the line is a #-directive, read the entire line and return a newline.
case '$':
letter:
p = token_buffer;
- while (isalnum (c) || c == '_' || c == '$' || c == '@')
+ while (ISALNUM (c) || c == '_' || c == '$' || c == '@')
{
/* Make sure this char really belongs in an identifier. */
if (c == '@' && ! doing_objc_thang)
next_c = GETC ();
UNGETC (next_c); /* Always undo this lookahead. */
- if (!isalnum (next_c) && next_c != '.')
+ if (!ISALNUM (next_c) && next_c != '.')
{
token_buffer[0] = (char)c, token_buffer[1] = '\0';
yylval.ttype = (c == '0') ? integer_zero_node : integer_one_node;
/* Read all the digits-and-decimal-points. */
while (c == '.'
- || (isalnum (c) && c != 'l' && c != 'L'
+ || (ISALNUM (c) && c != 'l' && c != 'L'
&& c != 'u' && c != 'U'
&& c != 'i' && c != 'I' && c != 'j' && c != 'J'
&& (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
only when it is followed by a digit.
Otherwise, unread the following non-digit
and use the '.' as a structural token. */
- if (p == token_buffer + 2 && !isdigit (c))
+ if (p == token_buffer + 2 && !ISDIGIT (c))
{
if (c == '.')
{
/* It is not a decimal point.
It should be a digit (perhaps a hex digit). */
- if (isdigit (c))
+ if (ISDIGIT (c))
{
c = c - '0';
}
if (floatflag != NOT_FLOAT)
{
tree type = double_type_node;
- int exceeds_double = 0;
int imag = 0;
+ int conversion_errno = 0;
REAL_VALUE_TYPE value;
jmp_buf handler;
*p++ = c;
c = GETC();
}
- if (! isdigit (c))
+ if (! ISDIGIT (c))
error ("floating constant exponent has no digits");
- while (isdigit (c))
+ while (ISDIGIT (c))
{
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
}
*p = 0;
- errno = 0;
/* Convert string to a double, checking for overflow. */
if (setjmp (handler))
error ("both `f' and `l' in floating constant");
type = float_type_node;
+ errno = 0;
value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+ conversion_errno = errno;
/* A diagnostic is required here by some ANSI C testsuites.
This is not pedwarn, become some people don't want
an error for this. */
else if (lflag)
{
type = long_double_type_node;
+ errno = 0;
value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+ conversion_errno = errno;
if (REAL_VALUE_ISINF (value) && pedantic)
warning ("floating point number exceeds range of `long double'");
}
else
{
+ errno = 0;
value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+ conversion_errno = errno;
if (REAL_VALUE_ISINF (value) && pedantic)
warning ("floating point number exceeds range of `double'");
}
set_float_handler (NULL_PTR);
}
#ifdef ERANGE
- if (errno == ERANGE && !flag_traditional && pedantic)
- {
- /* ERANGE is also reported for underflow,
- so test the value to distinguish overflow from that. */
- if (REAL_VALUES_LESS (dconst1, value)
- || REAL_VALUES_LESS (value, dconstm1))
- {
- warning ("floating point number exceeds range of `double'");
- exceeds_double = 1;
- }
- }
+ /* ERANGE is also reported for underflow,
+ so test the value to distinguish overflow from that. */
+ if (conversion_errno == ERANGE && !flag_traditional && pedantic
+ && (REAL_VALUES_LESS (dconst1, value)
+ || REAL_VALUES_LESS (value, dconstm1)))
+ warning ("floating point number exceeds range of `double'");
#endif
/* If the result is not a number, assume it must have been
int spec_imag = 0;
int bytes, warn, i;
+ traditional_type = ansi_type = type = NULL_TREE;
while (1)
{
if (c == 'u' || c == 'U')
UNGETC (c);
*p = 0;
- if (isalnum (c) || c == '.' || c == '_' || c == '$'
+ if (ISALNUM (c) || c == '.' || c == '_' || c == '$'
|| (!flag_traditional && (c == '-' || c == '+')
&& (p[-1] == 'e' || p[-1] == 'E')))
error ("missing white space after number `%s'", token_buffer);
&& (unsigned) c >= (1 << width))
pedwarn ("escape sequence out of range for character");
#ifdef MAP_CHARACTER
- if (isprint (c))
+ if (ISPRINT (c))
c = MAP_CHARACTER (c);
#endif
}
else if (TREE_UNSIGNED (char_type_node)
|| ((result >> (num_bits - 1)) & 1) == 0)
yylval.ttype
- = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0
+ = build_int_2 (result & (~(unsigned HOST_WIDE_INT) 0
>> (HOST_BITS_PER_WIDE_INT - num_bits)),
0);
else
yylval.ttype
- = build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0
+ = build_int_2 (result | ~(~(unsigned HOST_WIDE_INT) 0
>> (HOST_BITS_PER_WIDE_INT - num_bits)),
-1);
TREE_TYPE (yylval.ttype) = integer_type_node;