static tree get_time_identifier PROTO((const char *));
static int check_newline PROTO((void));
+static int whitespace_cr PROTO((int));
static int skip_white_space PROTO((int));
static void finish_defarg PROTO((void));
static int my_get_run_time PROTO((void));
char *token_buffer; /* Pointer to token buffer.
Actual allocated length is maxtoken + 2. */
-static int indent_level = 0; /* Number of { minus number of }. */
+static int indent_level; /* Number of { minus number of }. */
#include "hash.h"
\f
/* Nonzero tells yylex to ignore \ in string constants. */
-static int ignore_escape_flag = 0;
+static int ignore_escape_flag;
static tree
get_time_identifier (name)
literal_codeset = getenv ("LANG");
#endif
-#if USE_CPPLIB
- parse_in.show_column = 1;
- if (! cpp_start_read (&parse_in, filename))
- abort ();
-
- /* cpp_start_read always puts at least one line directive into the
- token buffer. We must arrange to read it out here. */
- yy_cur = parse_in.token_buffer;
- yy_lim = CPP_PWRITTEN (&parse_in);
- cpp_token = CPP_DIRECTIVE;
-
-#else
+#if !USE_CPPLIB
/* Open input file. */
if (filename == 0 || !strcmp (filename, "-"))
{
#ifdef IO_BUFFER_SIZE
setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
#endif
+#else /* !USE_CPPLIB */
+ parse_in.show_column = 1;
+ if (! cpp_start_read (&parse_in, filename))
+ abort ();
+
+ if (filename == 0 || !strcmp (filename, "-"))
+ filename = "stdin";
+
+ /* cpp_start_read always puts at least one line directive into the
+ token buffer. We must arrange to read it out here. */
+ yy_cur = parse_in.token_buffer;
+ yy_lim = CPP_PWRITTEN (&parse_in);
+ cpp_token = CPP_DIRECTIVE;
+
#endif /* !USE_CPPLIB */
/* Initialize the lookahead machinery. */
ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
ridpointers[(int) RID_INLINE] = get_identifier ("inline");
ridpointers[(int) RID_CONST] = get_identifier ("const");
- ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
ridpointers[(int) RID_RESTRICT] = get_identifier ("__restrict");
+ ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
ridpointers[(int) RID_AUTO] = get_identifier ("auto");
ridpointers[(int) RID_STATIC] = get_identifier ("static");
ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
if (IDENTIFIER_POINTER (t))
fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
break;
+
case AGGR:
if (yylval.ttype == class_type_node)
fprintf (file, " `class'");
else
my_friendly_abort (80);
break;
+
+ case CONSTANT:
+ t = yylval.ttype;
+ 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
+ " 0x%x%016x",
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+ " 0x%lx%016lx",
+#else
+ " 0x%llx%016llx",
+#endif
+#endif
+#else
+#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
+ " 0x%lx%08lx",
+#else
+ " 0x%x%08x",
+#endif
+#endif
+ TREE_INT_CST_HIGH (t), TREE_INT_CST_LOW (t));
+ break;
}
}
/* Unget a character from the input stream. */
if (yychar == YYEMPTY || rescan == 0)
{
+ /* If we're putting back a brace, undo the change in indent_level
+ from the first time we saw it. */
+ if (ch == '{')
+ indent_level--;
+ else if (ch == '}')
+ indent_level++;
+
put_back (ch);
}
else
int look_for_lbrac = 0;
if (pyychar == '{')
- obstack_1grow (obstackp, '{');
+ {
+ obstack_1grow (obstackp, '{');
+ /* We incremented indent_level in yylex; undo that. */
+ indent_level--;
+ }
else if (pyychar == '=')
look_for_semicolon = 1;
else if (pyychar == ':')
clear_anon_tags ();
}
\f
+/* Iff C is a carriage return, warn about it - if appropriate -
+ and return nonzero. */
+static int
+whitespace_cr (c)
+ int c;
+{
+ static int newline_warning = 0;
+
+ if (c == '\r')
+ {
+ /* ANSI C says the effects of a carriage return in a source file
+ are undefined. */
+ if (pedantic && !newline_warning)
+ {
+ warning ("carriage return in source file");
+ warning ("(we only warn about the first carriage return)");
+ newline_warning = 1;
+ }
+ return 1;
+ }
+ return 0;
+}
+
/* If C is not whitespace, return C.
Otherwise skip whitespace and return first nonwhite char read. */
{
switch (c)
{
+ /* We don't recognize comments here, because
+ cpp output can include / and * consecutively as operators.
+ Also, there's no need, since cpp removes all comments. */
+
case '\n':
if (linemode)
{
case ' ':
case '\t':
case '\f':
- case '\r':
case '\v':
case '\b':
#if USE_CPPLIB
c = getch ();
break;
+ case '\r':
+ whitespace_cr (c);
+ c = getch ();
+ break;
+
case '\\':
c = getch ();
if (c == '\n')
return token_buffer + offset;
}
\f
+#if defined HANDLE_PRAGMA
+/* Local versions of these macros, that can be passed as function pointers. */
+static int
+pragma_getc ()
+{
+ return getch ();
+}
+
+static void
+pragma_ungetc (arg)
+ int arg;
+{
+ put_back (arg);
+}
+#endif
+
static int
read_line_number (num)
int *num;
int saw_line;
enum { act_none, act_push, act_pop } action;
int old_lineno, action_number, l;
- int entering_system_header;
int entering_c_header;
restart:
if (!strcmp (name, "pragma"))
{
token = real_yylex ();
- if (token == IDENTIFIER
- && TREE_CODE (yylval.ttype) == IDENTIFIER_NODE)
- {
- /* If this is 1, we handled it; if it's -1, it was one we
- wanted but had something wrong with it. Only if it's
- 0 was it not handled. */
- if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype)))
- goto skipline;
- }
- else if (token == END_OF_LINE)
+ if (token != IDENTIFIER
+ || TREE_CODE (yylval.ttype) != IDENTIFIER_NODE)
+ goto skipline;
+
+ /* If this is 1, we handled it; if it's -1, it was one we
+ wanted but had something wrong with it. Only if it's
+ 0 was it not handled. */
+ if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype)))
goto skipline;
#ifdef HANDLE_PRAGMA
(if both are defined), in order to give the back
end a chance to override the interpretation of
SYSV style pragmas. */
- if (HANDLE_PRAGMA (getch, put_back,
+ if (HANDLE_PRAGMA (pragma_getc, pragma_ungetc,
IDENTIFIER_POINTER (yylval.ttype)))
goto skipline;
#endif /* HANDLE_PRAGMA */
extract_interface_info ();
old_lineno = lineno;
- entering_system_header = 0;
- entering_c_header = 0;
action = act_none;
action_number = 0;
lineno = l;
+ /* Each change of file name
+ reinitializes whether we are now in a system header. */
+ in_system_header = 0;
+ entering_c_header = 0;
+
if (!read_line_number (&action_number))
{
/* Update the name in the top element of input_file_stack. */
if (action_number == 3)
{
/* `3' after file name means this is a system header file. */
- entering_system_header = 1;
+ in_system_header = 1;
read_line_number (&action_number);
}
if (action_number == 4)
if (action == act_push)
{
/* Pushing to a new file. */
- struct file_stack *p;
-
- p = (struct file_stack *) xmalloc (sizeof (struct file_stack));
+ struct file_stack *p
+ = (struct file_stack *) xmalloc (sizeof (struct file_stack));
input_file_stack->line = old_lineno;
p->next = input_file_stack;
p->name = input_filename;
input_file_stack = p;
input_file_stack_tick++;
debug_start_source_file (input_filename);
- in_system_header = entering_system_header;
if (c_header_level)
++c_header_level;
else if (entering_c_header)
/* Popping out of a file. */
if (input_file_stack->next)
{
- struct file_stack *p;
+ struct file_stack *p = input_file_stack;
if (c_header_level && --c_header_level == 0)
{
warning ("badly nested C headers from preprocessor");
--pending_lang_change;
}
- in_system_header = entering_system_header;
- p = input_file_stack;
if (indent_level != p->indent_level)
{
warning_with_file_and_line
else
error ("#-lines for entering and leaving files don't match");
}
- else
- in_system_header = entering_system_header;
+
+ /* Now that we've pushed or popped the input stack,
+ update the name in the top element. */
+ if (input_file_stack)
+ input_file_stack->name = input_filename;
/* skip the rest of this line. */
skipline:
linemode = 0;
end_of_file = 0;
- while ((c = getch ()) != EOF && c != '\n');
+ do
+ c = getch ();
+ while (c != '\n' && c != EOF);
return c;
}
+\f
+#ifdef HANDLE_GENERIC_PRAGMAS
+
+/* Handle a #pragma directive.
+ TOKEN is the token we read after `#pragma'. Processes the entire input
+ line and return non-zero iff the pragma has been successfully parsed. */
+
+/* This function has to be in this file, in order to get at
+ the token types. */
+
+static int
+handle_generic_pragma (token)
+ register int token;
+{
+ for (;;)
+ {
+ switch (token)
+ {
+ case IDENTIFIER:
+ case TYPENAME:
+ case STRING:
+ case CONSTANT:
+ handle_pragma_token (token_buffer, yylval.ttype);
+ break;
+
+ case LEFT_RIGHT:
+ handle_pragma_token ("(", NULL_TREE);
+ handle_pragma_token (")", NULL_TREE);
+ break;
+
+ case END_OF_LINE:
+ return handle_pragma_token (NULL_PTR, NULL_TREE);
+
+ default:
+ handle_pragma_token (token_buffer, NULL_TREE);
+ }
+
+ token = real_yylex ();
+ }
+}
+#endif /* HANDLE_GENERIC_PRAGMAS */
+
+static int
+handle_cp_pragma (pname)
+ const char *pname;
+{
+ register int token;
+
+ if (! strcmp (pname, "vtable"))
+ {
+ extern tree pending_vtables;
+
+ /* More follows: it must be a string constant (class name). */
+ token = real_yylex ();
+ if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid #pragma vtable");
+ return -1;
+ }
+
+ pending_vtables
+ = perm_tree_cons (NULL_TREE,
+ get_identifier (TREE_STRING_POINTER (yylval.ttype)),
+ pending_vtables);
+ token = real_yylex ();
+ if (token != END_OF_LINE)
+ warning ("trailing characters ignored");
+ return 1;
+ }
+ else if (! strcmp (pname, "unit"))
+ {
+ /* More follows: it must be a string constant (unit name). */
+ token = real_yylex ();
+ if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid #pragma unit");
+ return -1;
+ }
+ token = real_yylex ();
+ if (token != END_OF_LINE)
+ warning ("trailing characters ignored");
+ return 1;
+ }
+ else if (! strcmp (pname, "interface"))
+ {
+ char *main_filename = input_filename;
+
+ main_filename = file_name_nondirectory (main_filename);
+
+ token = real_yylex ();
+
+ if (token != END_OF_LINE)
+ {
+ if (token != STRING
+ || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid `#pragma interface'");
+ return -1;
+ }
+ main_filename = TREE_STRING_POINTER (yylval.ttype);
+ token = real_yylex ();
+ }
+
+ if (token != END_OF_LINE)
+ warning ("garbage after `#pragma interface' ignored");
+
+ cp_pragma_interface (main_filename);
+
+ return 1;
+ }
+ else if (! strcmp (pname, "implementation"))
+ {
+ char *main_filename = main_input_filename ? main_input_filename : input_filename;
+
+ main_filename = file_name_nondirectory (main_filename);
+
+ token = real_yylex ();
+
+ if (token != END_OF_LINE)
+ {
+ if (token != STRING
+ || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid `#pragma implementation'");
+ return -1;
+ }
+ main_filename = TREE_STRING_POINTER (yylval.ttype);
+ token = real_yylex ();
+ }
+
+ if (token != END_OF_LINE)
+ warning ("garbage after `#pragma implementation' ignored");
+
+ cp_pragma_implementation (main_filename);
+ return 1;
+ }
+
+ return 0;
+}
+\f
void
do_pending_lang_change ()
{
;
else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
|| (count > 1
- && (((unsigned)1 <<
- (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
+ && (((unsigned)1
+ << (TYPE_PRECISION (integer_type_node)
+ - (count - 1) * 4))
<= firstdig)))
pedwarn ("hex escape out of range");
return code;
pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c);
return c;
}
+\f
+void
+yyerror (string)
+ const char *string;
+{
+ extern int end_of_file;
+ char buf[200];
+
+ strcpy (buf, string);
+
+ /* We can't print string and character constants well
+ because the token_buffer contains the result of processing escapes. */
+ if (end_of_file)
+ strcat (buf, input_redirected ()
+ ? " at end of saved text"
+ : " at end of input");
+ else if (token_buffer[0] == 0)
+ strcat (buf, " at null character");
+ else if (token_buffer[0] == '"')
+ strcat (buf, " before string constant");
+ else if (token_buffer[0] == '\'')
+ strcat (buf, " before character constant");
+ else if (!ISGRAPH ((unsigned char)token_buffer[0]))
+ sprintf (buf + strlen (buf), " before character 0%o",
+ (unsigned char) token_buffer[0]);
+ else
+ strcat (buf, " before `%s'");
+ error (buf, token_buffer);
+}
+\f
/* Value is 1 (or 2) if we should try to make the next identifier look like
a typename (when it may be a local variable or a class variable).
Value is 0 if we treat this name in a default fashion. */
return NULL_TREE;
}
-struct pf_args
+struct pf_args
{
/* Input */
+ int base;
+ char * p;
/* I/O */
- char *p;
int c;
+ /* Output */
int imag;
tree type;
- /* Output */
+ int conversion_errno;
REAL_VALUE_TYPE value;
};
REAL_VALUE_ATOF may not work any more. */
char *copy = (char *) alloca (args->p - token_buffer + 1);
bcopy (token_buffer, copy, args->p - token_buffer + 1);
-
+ args->imag = 0;
+ args->conversion_errno = 0;
+ args->type = double_type_node;
+
while (1)
{
int lose = 0;
-
+
/* Read the suffixes to choose a data type. */
switch (args->c)
{
error ("more than one `f' in numeric constant");
fflag = 1;
break;
-
+
case 'l': case 'L':
if (lflag)
error ("more than one `l' in numeric constant");
lflag = 1;
break;
-
+
case 'i': case 'I':
if (args->imag)
error ("more than one `i' or `j' in numeric constant");
pedwarn ("ANSI C++ forbids imaginary numeric constants");
args->imag = 1;
break;
-
+
default:
lose = 1;
}
-
+
if (lose)
break;
-
+
if (args->p >= token_buffer + maxtoken - 3)
args->p = extend_token_buffer (args->p);
*(args->p++) = args->c;
*(args->p) = 0;
args->c = getch ();
}
-
+
/* The second argument, machine_mode, of REAL_VALUE_ATOF
tells the desired precision of the binary result
of decimal-to-binary conversion. */
-
+
if (fflag)
{
if (lflag)
error ("both `f' and `l' in floating constant");
-
+
args->type = float_type_node;
- args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ errno = 0;
+ if (args->base == 16)
+ args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
+ else
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ args->conversion_errno = errno;
/* A diagnostic is required here by some ANSI C testsuites.
- This is not pedwarn, become some people don't want
+ This is not pedwarn, because some people don't want
an error for this. */
if (REAL_VALUE_ISINF (args->value) && pedantic)
warning ("floating point number exceeds range of `float'");
else if (lflag)
{
args->type = long_double_type_node;
- args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ errno = 0;
+ if (args->base == 16)
+ args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
+ else
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ args->conversion_errno = errno;
if (REAL_VALUE_ISINF (args->value) && pedantic)
warning ("floating point number exceeds range of `long double'");
}
else
{
- args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ errno = 0;
+ if (args->base == 16)
+ args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
+ else
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ args->conversion_errno = errno;
if (REAL_VALUE_ISINF (args->value) && pedantic)
warning ("floating point number exceeds range of `double'");
}
real_yylex ()
{
register int c;
+ register char *p;
register int value;
int wide_flag = 0;
- int dollar_seen = 0;
- int i;
c = getch ();
switch (c)
{
case EOF:
- token_buffer[0] = '\0';
end_of_file = 1;
+ token_buffer[0] = 0;
if (input_redirected ())
value = END_OF_SAVED_INPUT;
else if (linemode)
value = ENDFILE;
break;
- case '$':
- if (! dollars_in_ident)
- error ("`$' in identifier");
- else if (pedantic)
- pedwarn ("`$' in identifier");
- dollar_seen = 1;
- goto letter;
-
case 'L':
#if USE_CPPLIB
if (cpp_token == CPP_NAME)
}
token_put_back (c);
}
-
+
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'M': case 'N': case 'O':
case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z':
case '_':
+ case '$':
letter:
- {
- register char *p;
-
#if USE_CPPLIB
- if (cpp_token == CPP_NAME)
- {
- /* Note that one character has already been read from
- yy_cur into token_buffer. */
-
- int len = yy_lim - yy_cur + 1;
- if (len >= maxtoken)
- extend_token_buffer_to (len + 1);
- memcpy (token_buffer + 1, yy_cur, len);
- p = token_buffer + len;
- yy_cur = yy_lim;
- }
- else
+ if (cpp_token == CPP_NAME)
+ {
+ /* Note that one character has already been read from
+ yy_cur into token_buffer. Also, cpplib complains about
+ $ in identifiers, so we don't have to. */
+
+ int len = yy_lim - yy_cur + 1;
+ if (len >= maxtoken)
+ extend_token_buffer_to (len + 1);
+ memcpy (token_buffer + 1, yy_cur, len);
+ p = token_buffer + len;
+ yy_cur = yy_lim;
+ }
+ else
#endif
- {
- /* We already installed C as the first char in token_buffer. */
- p = token_buffer+1;
- c = token_getch ();
-
- while (ISALNUM (c) || (c == '_') || c == '$')
- {
- if (c == '$')
- {
- if (! dollars_in_ident)
- error ("`$' in identifier");
- else if (pedantic)
- pedwarn ("`$' in identifier");
- }
+ {
+ p = token_buffer;
+ while (ISALNUM (c) || (c == '_') || c == '$')
+ {
+ /* Make sure this char really belongs in an identifier. */
+ if (c == '$')
+ {
+ if (! dollars_in_ident)
+ error ("`$' in identifier");
+ else if (pedantic)
+ pedwarn ("`$' in identifier");
+ }
- if (p >= token_buffer + maxtoken)
- p = extend_token_buffer (p);
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
- *p++ = c;
- c = token_getch ();
- }
+ *p++ = c;
+ c = token_getch ();
+ }
- *p = 0;
- token_put_back (c);
- }
+ *p = 0;
+ token_put_back (c);
+ }
- value = IDENTIFIER;
- yylval.itype = 0;
+ value = IDENTIFIER;
+ yylval.itype = 0;
- /* Try to recognize a keyword. Uses minimum-perfect hash function */
+ /* Try to recognize a keyword. Uses minimum-perfect hash function */
- {
- register struct resword *ptr;
+ {
+ register struct resword *ptr;
- if ((ptr = is_reserved_word (token_buffer, p - token_buffer)))
- {
- if (ptr->rid)
- {
- tree old_ttype = ridpointers[(int) ptr->rid];
-
- /* If this provides a type for us, then revert lexical
- state to standard state. */
- if (TREE_CODE (old_ttype) == IDENTIFIER_NODE
- && IDENTIFIER_GLOBAL_VALUE (old_ttype) != 0
- && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL)
- looking_for_typename = 0;
- else if (ptr->token == AGGR || ptr->token == ENUM)
- looking_for_typename = 2;
-
- if (ptr->token == VISSPEC)
- {
- switch (ptr->rid)
- {
- case RID_PUBLIC:
- yylval.ttype = access_public_node;
- break;
- case RID_PRIVATE:
- yylval.ttype = access_private_node;
- break;
- case RID_PROTECTED:
- yylval.ttype = access_protected_node;
- break;
- default:
- my_friendly_abort (63);
- }
- }
- else
- yylval.ttype = old_ttype;
- }
- else switch (ptr->token)
- {
- case EQCOMPARE:
- yylval.code = NE_EXPR;
- token_buffer[0] = '!';
- token_buffer[1] = '=';
- token_buffer[2] = 0;
- break;
+ if ((ptr = is_reserved_word (token_buffer, p - token_buffer)))
+ {
+ if (ptr->rid)
+ {
+ if (ptr->token == VISSPEC)
+ {
+ switch (ptr->rid)
+ {
+ case RID_PUBLIC:
+ yylval.ttype = access_public_node;
+ break;
+ case RID_PRIVATE:
+ yylval.ttype = access_private_node;
+ break;
+ case RID_PROTECTED:
+ yylval.ttype = access_protected_node;
+ break;
+ default:
+ my_friendly_abort (63);
+ }
+ }
+ else
+ yylval.ttype = ridpointers[(int) ptr->rid];
+ }
+ else switch (ptr->token)
+ {
+ case EQCOMPARE:
+ yylval.code = NE_EXPR;
+ token_buffer[0] = '!';
+ token_buffer[1] = '=';
+ token_buffer[2] = 0;
+ break;
- case ASSIGN:
- if (strcmp ("and_eq", token_buffer) == 0)
- {
- yylval.code = BIT_AND_EXPR;
- token_buffer[0] = '&';
- }
- else if (strcmp ("or_eq", token_buffer) == 0)
- {
- yylval.code = BIT_IOR_EXPR;
- token_buffer[0] = '|';
- }
- else if (strcmp ("xor_eq", token_buffer) == 0)
- {
- yylval.code = BIT_XOR_EXPR;
- token_buffer[0] = '^';
- }
- token_buffer[1] = '=';
- token_buffer[2] = 0;
- break;
+ case ASSIGN:
+ if (strcmp ("and_eq", token_buffer) == 0)
+ {
+ yylval.code = BIT_AND_EXPR;
+ token_buffer[0] = '&';
+ }
+ else if (strcmp ("or_eq", token_buffer) == 0)
+ {
+ yylval.code = BIT_IOR_EXPR;
+ token_buffer[0] = '|';
+ }
+ else if (strcmp ("xor_eq", token_buffer) == 0)
+ {
+ yylval.code = BIT_XOR_EXPR;
+ token_buffer[0] = '^';
+ }
+ token_buffer[1] = '=';
+ token_buffer[2] = 0;
+ break;
- case '&':
- yylval.code = BIT_AND_EXPR;
- token_buffer[0] = '&';
- token_buffer[1] = 0;
- break;
+ case '&':
+ yylval.code = BIT_AND_EXPR;
+ token_buffer[0] = '&';
+ token_buffer[1] = 0;
+ break;
- case '|':
- yylval.code = BIT_IOR_EXPR;
- token_buffer[0] = '|';
- token_buffer[1] = 0;
- break;
+ case '|':
+ yylval.code = BIT_IOR_EXPR;
+ token_buffer[0] = '|';
+ token_buffer[1] = 0;
+ break;
- case '^':
- yylval.code = BIT_XOR_EXPR;
- token_buffer[0] = '^';
- token_buffer[1] = 0;
- break;
- }
+ case '^':
+ yylval.code = BIT_XOR_EXPR;
+ token_buffer[0] = '^';
+ token_buffer[1] = 0;
+ break;
+ }
- value = (int) ptr->token;
- }
- }
+ value = (int) ptr->token;
+ }
+ }
- /* If we did not find a keyword, look for an identifier
- (or a typename). */
+ /* If we did not find a keyword, look for an identifier
+ (or a typename). */
- if (value == IDENTIFIER || value == TYPESPEC)
- GNU_xref_ref (current_function_decl, token_buffer);
+ if (value == IDENTIFIER || value == TYPESPEC)
+ GNU_xref_ref (current_function_decl, token_buffer);
- if (value == IDENTIFIER)
- {
- register tree tmp = get_identifier (token_buffer);
+ if (value == IDENTIFIER)
+ {
+ register tree tmp = get_identifier (token_buffer);
#if !defined(VMS) && defined(JOINER)
- /* Make sure that user does not collide with our internal
- naming scheme. */
- if (JOINER == '$'
- && dollar_seen
- && (THIS_NAME_P (tmp)
- || VPTR_NAME_P (tmp)
- || DESTRUCTOR_NAME_P (tmp)
- || VTABLE_NAME_P (tmp)
- || TEMP_NAME_P (tmp)
- || ANON_AGGRNAME_P (tmp)
- || ANON_PARMNAME_P (tmp)))
- warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
- token_buffer);
+ /* Make sure that user does not collide with our internal
+ naming scheme. */
+ if (JOINER == '$'
+ && (THIS_NAME_P (tmp)
+ || VPTR_NAME_P (tmp)
+ || DESTRUCTOR_NAME_P (tmp)
+ || VTABLE_NAME_P (tmp)
+ || TEMP_NAME_P (tmp)
+ || ANON_AGGRNAME_P (tmp)
+ || ANON_PARMNAME_P (tmp)))
+ warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
+ token_buffer);
#endif
- yylval.ttype = tmp;
- }
- if (value == NEW && ! global_bindings_p ())
- {
- value = NEW;
- goto done;
- }
- }
-
+ yylval.ttype = tmp;
+ }
+ if (value == NEW && ! global_bindings_p ())
+ {
+ value = NEW;
+ goto done;
+ }
break;
case '.':
if (ISDIGIT (c1))
{
token_put_back (c1);
- goto resume_numerical_scan;
+ goto number;
}
token_put_back (c1);
}
value = '.';
token_buffer[1] = 0;
- goto done;
+ break;
case '0': case '1':
/* Optimize for most frequent case. */
#endif
if (cond)
{
- /* Terminate string. */
- if (c == '0')
- yylval.ttype = integer_zero_node;
- else
- yylval.ttype = integer_one_node;
+ yylval.ttype = (c == '0') ? integer_zero_node : integer_one_node;
value = CONSTANT;
- goto done;
+ break;
}
+ /*FALLTHRU*/
}
- /* fall through... */
- case '2': case '3': case '4':
+ case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- resume_numerical_scan:
+ number:
{
- register char *p;
int base = 10;
int count = 0;
int largest_digit = 0;
#define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2)
unsigned int parts[TOTAL_PARTS];
- enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
- = NOT_FLOAT;
+ enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS, AFTER_EXPON }
+ floatflag = NOT_FLOAT;
for (count = 0; count < TOTAL_PARTS; count++)
parts[count] = 0;
/* Read all the digits-and-decimal-points. */
while (c == '.'
- || (ISALNUM (c) && (c != 'l') && (c != 'L')
- && (c != 'u') && (c != 'U')
+ || (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')))))
{
if (c == '.')
{
- if (base == 16)
- error ("floating constant may not be in radix 16");
+ if (base == 16 && pedantic)
+ pedwarn ("floating constant may not be in radix 16");
if (floatflag == TOO_MANY_POINTS)
/* We have already emitted an error. Don't need another. */
;
- else if (floatflag == AFTER_POINT)
+ else if (floatflag == AFTER_POINT || floatflag == AFTER_EXPON)
{
error ("malformed floating constant");
floatflag = TOO_MANY_POINTS;
else
floatflag = AFTER_POINT;
- base = 10;
+ if (base == 8)
+ base = 10;
*p++ = c = token_getch ();
/* Accept '.' as the start of a floating-point number
only when it is followed by a digit. */
if (c == 'e' || c == 'E')
{
base = 10;
- floatflag = AFTER_POINT;
+ floatflag = AFTER_EXPON;
break; /* start of exponent */
}
error ("nondigits in number and not hexadecimal");
c = 0;
}
+ else if (base == 16 && (c == 'p' || c == 'P'))
+ {
+ floatflag = AFTER_EXPON;
+ break; /* start of exponent */
+ }
else if (c >= 'a')
{
c = c - 'a' + 10;
if (floatflag != NOT_FLOAT)
{
- tree type = double_type_node;
- int exceeds_double = 0;
- int imag = 0;
+ tree type;
+ int imag, conversion_errno;
REAL_VALUE_TYPE value;
struct pf_args args;
/* Read explicit exponent if any, and put it in tokenbuf. */
- if ((c == 'e') || (c == 'E'))
+ if ((base == 10 && ((c == 'e') || (c == 'E')))
+ || (base == 16 && (c == 'p' || c == 'P')))
{
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
*p++ = c;
c = token_getch ();
}
+ /* Exponent is decimal, even if string is a hex float. */
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);
c = token_getch ();
}
}
+ if (base == 16 && floatflag != AFTER_EXPON)
+ error ("hexadecimal floating constant has no exponent");
*p = 0;
- errno = 0;
/* Setup input for parse_float() */
+ args.base = base;
args.p = p;
args.c = c;
- args.imag = imag;
- args.type = type;
-
+
/* Convert string to a double, checking for overflow. */
if (do_float_handler (parse_float, (PTR) &args))
{
}
/* Receive output from parse_float() */
- p = args.p;
c = args.c;
imag = args.imag;
type = args.type;
+ conversion_errno = args.conversion_errno;
#ifdef ERANGE
- if (errno == ERANGE && 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))
- {
- pedwarn ("floating point number exceeds range of `%s'",
- IDENTIFIER_POINTER (TYPE_IDENTIFIER (type)));
- exceeds_double = 1;
- }
- }
+ /* ERANGE is also reported for underflow,
+ so test the value to distinguish overflow from that. */
+ if (conversion_errno == ERANGE && 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
/* Create a node with determined type and value. */
if (imag)
yylval.ttype = build_complex (NULL_TREE,
- cp_convert (type, integer_zero_node),
+ convert (type, integer_zero_node),
build_real (type, value));
else
yylval.ttype = build_real (type, value);
int spec_long = 0;
int spec_long_long = 0;
int spec_imag = 0;
- int warn;
+ int warn, i;
while (1)
{
/* This is simplified by the fact that our constant
is always positive. */
+
high = low = 0;
for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++)
<< (i * HOST_BITS_PER_CHAR));
low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);
}
-
-
+
yylval.ttype = build_int_2 (low, high);
TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;
/* Calculate the ANSI type. */
- if (!spec_long && !spec_unsigned
+ if (! spec_long && ! spec_unsigned
&& int_fits_type_p (yylval.ttype, integer_type_node))
type = integer_type_node;
- else if (!spec_long && (base != 10 || spec_unsigned)
+ else if (! spec_long && (base != 10 || spec_unsigned)
&& int_fits_type_p (yylval.ttype, unsigned_type_node))
- /* Nondecimal constants try unsigned even in traditional C. */
type = unsigned_type_node;
- else if (!spec_unsigned && !spec_long_long
+ else if (! spec_unsigned && !spec_long_long
&& int_fits_type_p (yylval.ttype, long_integer_type_node))
type = long_integer_type_node;
- else if (! spec_long_long)
+ else if (! spec_long_long
+ && int_fits_type_p (yylval.ttype,
+ long_unsigned_type_node))
type = long_unsigned_type_node;
else if (! spec_unsigned
- /* Verify value does not overflow into sign bit. */
- && TREE_INT_CST_HIGH (yylval.ttype) >= 0
&& int_fits_type_p (yylval.ttype,
long_long_integer_type_node))
type = long_long_integer_type_node;
else
type = widest_unsigned_literal_type_node;
- if (!int_fits_type_p (yylval.ttype, type) && !warn)
- pedwarn ("integer constant is larger than the maximum value for its type");
+ if (pedantic && !spec_long_long && !warn
+ && (TYPE_PRECISION (long_integer_type_node)
+ < TYPE_PRECISION (type)))
+ {
+ warn = 1;
+ pedwarn ("integer constant larger than the maximum value of an unsigned long int");
+ }
if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
- warning ("decimal integer constant is so large that it is unsigned");
+ warning ("decimal constant is so large that it is unsigned");
if (spec_imag)
{
<= TYPE_PRECISION (integer_type_node))
yylval.ttype
= build_complex (NULL_TREE, integer_zero_node,
- cp_convert (integer_type_node,
- yylval.ttype));
+ convert (integer_type_node,
+ yylval.ttype));
else
error ("complex integer constant is too wide for `__complex int'");
}
else
TREE_TYPE (yylval.ttype) = type;
+
+
+ /* If it's still an integer (not a complex), and it doesn't
+ fit in the type we choose for it, then pedwarn. */
+
+ if (! warn
+ && TREE_CODE (TREE_TYPE (yylval.ttype)) == INTEGER_TYPE
+ && ! int_fits_type_p (yylval.ttype, TREE_TYPE (yylval.ttype)))
+ pedwarn ("integer constant is larger than the maximum value for its type");
}
token_put_back (c);
*p = 0;
+ if (ISALNUM (c) || c == '.' || c == '_' || c == '$'
+ || ((c == '-' || c == '+')
+ && (p[-1] == 'e' || p[-1] == 'E')))
+ error ("missing white space after number `%s'", token_buffer);
+
value = CONSTANT; break;
}
}
/* Merge character into result; ignore excess chars. */
- num_chars++;
+ num_chars += (width / TYPE_PRECISION (char_type_node));
if (num_chars < max_chars + 1)
{
if (width < HOST_BITS_PER_INT)
= build_int_2 (result | ~(~(unsigned HOST_WIDE_INT) 0
>> (HOST_BITS_PER_WIDE_INT - num_bits)),
-1);
+ /* In C, a character constant has type 'int'; in C++, 'char'. */
if (chars_seen <= 1)
TREE_TYPE (yylval.ttype) = char_type_node;
else
case '"':
string_constant:
{
- register char *p;
unsigned width = wide_flag ? WCHAR_TYPE_SIZE
: TYPE_PRECISION (char_type_node);
#ifdef MULTIBYTE_CHARS
goto skipnewline;
if (width < HOST_BITS_PER_INT
&& (unsigned) c >= ((unsigned)1 << width))
- warning ("escape sequence out of range for character");
+ pedwarn ("escape sequence out of range for character");
}
else if (c == '\n')
{
for (byte = 0; byte < WCHAR_BYTES; ++byte)
{
int value;
- if (byte >= (int) sizeof(c))
+ if (byte >= (int) sizeof (c))
value = 0;
else
value = (c >> (byte * width)) & bytemask;
skipnewline:
c = token_getch ();
- if (c == EOF) {
- error ("Unterminated string");
- break;
- }
}
/* Terminate the string value, either with a single byte zero
*p++ = 0;
}
+ if (c == EOF)
+ error ("Unterminated string constant");
+
/* We have read the entire constant.
Construct a STRING_CST for the result. */
case '-':
case '&':
case '|':
+ case ':':
case '<':
case '>':
case '*':
case '>':
c = RSHIFT;
goto combine;
+ case ':':
+ value = SCOPE;
+ yylval.itype = 1;
+ goto done;
}
- else if ((c == '-') && (c1 == '>'))
- {
- c1 = token_getch ();
- if (c1 == '*')
- value = POINTSAT_STAR;
- else
- {
- token_put_back (c1);
- value = POINTSAT;
- }
- goto done;
- }
else if (c1 == '?' && (c == '<' || c == '>'))
{
token_buffer[3] = 0;
token_buffer);
goto done;
}
- /* digraphs */
- else if (c == '<' && c1 == '%')
- { value = '{'; goto done; }
- else if (c == '<' && c1 == ':')
- { value = '['; goto done; }
- else if (c == '%' && c1 == '>')
- { value = '}'; goto done; }
- else if (c == '%' && c1 == ':')
- { value = '#'; goto done; }
+ else
+ switch (c)
+ {
+ case '-':
+ if (c1 == '>')
+ {
+ c1 = token_getch ();
+ if (c1 == '*')
+ value = POINTSAT_STAR;
+ else
+ {
+ token_put_back (c1);
+ value = POINTSAT;
+ }
+ goto done;
+ }
+ break;
+
+ /* digraphs */
+ case ':':
+ if (c1 == '>')
+ { value = ']'; goto done; }
+ break;
+ case '<':
+ if (c1 == '%')
+ { value = '{'; indent_level++; goto done; }
+ if (c1 == ':')
+ { value = '['; goto done; }
+ break;
+ case '%':
+ if (c1 == '>')
+ { value = '}'; indent_level--; goto done; }
+ break;
+ }
token_put_back (c1);
token_buffer[1] = 0;
+ /* Here the C frontend changes < and > to ARITHCOMPARE. We don't
+ do that because of templates. */
+
value = c;
- goto done;
+ break;
}
- case ':':
- c = token_getch ();
- if (c == ':')
- {
- token_buffer[1] = ':';
- token_buffer[2] = '\0';
- value = SCOPE;
- yylval.itype = 1;
- }
- else if (c == '>')
- {
- value = ']';
- goto done;
- }
- else
- {
- token_put_back (c);
- value = ':';
- }
- break;
-
case 0:
/* Don't make yyparse think this is eof. */
value = 1;
break;
+ case '{':
+ indent_level++;
+ value = c;
+ break;
+
+ case '}':
+ indent_level--;
+ value = c;
+ break;
+
default:
value = c;
}
error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
}
\f
-void
-yyerror (string)
- const char *string;
-{
- extern int end_of_file;
- char buf[200];
-
- strcpy (buf, string);
-
- /* We can't print string and character constants well
- because the token_buffer contains the result of processing escapes. */
- if (end_of_file)
- strcat (buf, input_redirected ()
- ? " at end of saved text"
- : " at end of input");
- else if (token_buffer[0] == 0)
- strcat (buf, " at null character");
- else if (token_buffer[0] == '"')
- strcat (buf, " before string constant");
- else if (token_buffer[0] == '\'')
- strcat (buf, " before character constant");
- else if (!ISGRAPH ((unsigned char)token_buffer[0]))
- sprintf (buf + strlen (buf), " before character 0%o",
- (unsigned char) token_buffer[0]);
- else
- strcat (buf, " before `%s'");
-
- error (buf, token_buffer);
-}
-\f
-static int
-handle_cp_pragma (pname)
- const char *pname;
-{
- register int token;
-
- if (! strcmp (pname, "vtable"))
- {
- extern tree pending_vtables;
-
- /* More follows: it must be a string constant (class name). */
- token = real_yylex ();
- if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid #pragma vtable");
- return -1;
- }
-
- pending_vtables
- = perm_tree_cons (NULL_TREE,
- get_identifier (TREE_STRING_POINTER (yylval.ttype)),
- pending_vtables);
- token = real_yylex ();
- if (token != END_OF_LINE)
- warning ("trailing characters ignored");
- return 1;
- }
- else if (! strcmp (pname, "unit"))
- {
- /* More follows: it must be a string constant (unit name). */
- token = real_yylex ();
- if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid #pragma unit");
- return -1;
- }
- token = real_yylex ();
- if (token != END_OF_LINE)
- warning ("trailing characters ignored");
- return 1;
- }
- else if (! strcmp (pname, "interface"))
- {
- char *main_filename = input_filename;
-
- main_filename = file_name_nondirectory (main_filename);
-
- token = real_yylex ();
-
- if (token != END_OF_LINE)
- {
- if (token != STRING
- || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid `#pragma interface'");
- return -1;
- }
- main_filename = TREE_STRING_POINTER (yylval.ttype);
- token = real_yylex ();
- }
-
- if (token != END_OF_LINE)
- warning ("garbage after `#pragma interface' ignored");
-
- cp_pragma_interface (main_filename);
-
- return 1;
- }
- else if (! strcmp (pname, "implementation"))
- {
- char *main_filename = main_input_filename ? main_input_filename : input_filename;
-
- main_filename = file_name_nondirectory (main_filename);
-
- token = real_yylex ();
-
- if (token != END_OF_LINE)
- {
- if (token != STRING
- || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid `#pragma implementation'");
- return -1;
- }
- main_filename = TREE_STRING_POINTER (yylval.ttype);
- token = real_yylex ();
- }
-
- if (token != END_OF_LINE)
- warning ("garbage after `#pragma implementation' ignored");
-
- cp_pragma_implementation (main_filename);
-
- return 1;
- }
-
- return 0;
-}
-
/* Return the type-qualifier corresponding to the identifier given by
RID. */
my_friendly_abort (0);
return TYPE_UNQUALIFIED;
}
-
-\f
-#ifdef HANDLE_GENERIC_PRAGMAS
-
-/* Handle a #pragma directive. TOKEN is the type of the word following
- the #pragma directive on the line. Process the entire input line and
- return non-zero iff the directive successfully parsed. */
-
-/* This function has to be in this file, in order to get at
- the token types. */
-
-static int
-handle_generic_pragma (token)
- register int token;
-{
- for (;;)
- {
- switch (token)
- {
- case IDENTIFIER:
- case TYPENAME:
- case STRING:
- case CONSTANT:
- handle_pragma_token (token_buffer, yylval.ttype);
- break;
-
- case LEFT_RIGHT:
- handle_pragma_token ("(", NULL_TREE);
- handle_pragma_token (")", NULL_TREE);
- break;
-
- case END_OF_LINE:
- return handle_pragma_token (NULL_PTR, NULL_TREE);
-
- default:
- handle_pragma_token (token_buffer, NULL_TREE);
- }
-
- token = real_yylex ();
- }
-}
-#endif /* HANDLE_GENERIC_PRAGMAS */