/* MD reader for GCC.
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
+ Copyright (C) 1987-2019 Free Software Foundation, Inc.
This file is part of GCC.
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+/* This file is compiled twice: once for the generator programs
+ once for the compiler. */
+#ifdef GENERATOR_FILE
#include "bconfig.h"
+#else
+#include "config.h"
+#endif
#include "system.h"
#include "coretypes.h"
+#ifdef GENERATOR_FILE
#include "errors.h"
+#endif /* #ifdef GENERATOR_FILE */
#include "statistics.h"
#include "vec.h"
#include "read-md.h"
+#ifndef GENERATOR_FILE
+
+/* Minimal reimplementation of errors.c for use by RTL frontend
+ within cc1. */
+
+int have_error = 0;
+
+#endif /* #ifndef GENERATOR_FILE */
+
+
/* Associates PTR (which can be a string, etc.) with the file location
specified by FILENAME and LINENO. */
struct ptr_loc {
/* Global singleton. */
-rtx_reader *rtx_reader_ptr;
+md_reader *md_reader_ptr;
/* Given an object that starts with a char * name field, return a hash
code for its name. */
/* Associate PTR with the file position given by FILENAME and LINENO. */
void
-rtx_reader::set_md_ptr_loc (const void *ptr, const char *filename, int lineno)
+md_reader::set_md_ptr_loc (const void *ptr, const char *filename, int lineno)
{
struct ptr_loc *loc;
position was set. */
const struct ptr_loc *
-rtx_reader::get_md_ptr_loc (const void *ptr)
+md_reader::get_md_ptr_loc (const void *ptr)
{
return (const struct ptr_loc *) htab_find (m_ptr_locs, &ptr);
}
/* Associate NEW_PTR with the same file position as OLD_PTR. */
void
-rtx_reader::copy_md_ptr_loc (const void *new_ptr, const void *old_ptr)
+md_reader::copy_md_ptr_loc (const void *new_ptr, const void *old_ptr)
{
const struct ptr_loc *loc = get_md_ptr_loc (old_ptr);
if (loc != 0)
directive for it to OUTF. */
void
-rtx_reader::fprint_md_ptr_loc (FILE *outf, const void *ptr)
+md_reader::fprint_md_ptr_loc (FILE *outf, const void *ptr)
{
const struct ptr_loc *loc = get_md_ptr_loc (ptr);
if (loc != 0)
/* Special fprint_md_ptr_loc for writing to STDOUT. */
void
-rtx_reader::print_md_ptr_loc (const void *ptr)
+md_reader::print_md_ptr_loc (const void *ptr)
{
fprint_md_ptr_loc (stdout, ptr);
}
may be null or empty. */
const char *
-rtx_reader::join_c_conditions (const char *cond1, const char *cond2)
+md_reader::join_c_conditions (const char *cond1, const char *cond2)
{
char *result;
const void **entry;
directive for COND if its original file position is known. */
void
-rtx_reader::fprint_c_condition (FILE *outf, const char *cond)
+md_reader::fprint_c_condition (FILE *outf, const char *cond)
{
const char **halves = (const char **) htab_find (m_joined_conditions, &cond);
if (halves != 0)
/* Special fprint_c_condition for writing to STDOUT. */
void
-rtx_reader::print_c_condition (const char *cond)
+md_reader::print_c_condition (const char *cond)
{
fprint_c_condition (stdout, cond);
}
va_start (ap, msg);
- fprintf (stderr, "%s:%d:%d: error: ", rtx_reader_ptr->get_filename (),
- rtx_reader_ptr->get_lineno (), rtx_reader_ptr->get_colno ());
+ fprintf (stderr, "%s:%d:%d: error: ", md_reader_ptr->get_filename (),
+ md_reader_ptr->get_lineno (),
+ md_reader_ptr->get_colno ());
vfprintf (stderr, msg, ap);
putc ('\n', stderr);
context[i] = '\0';
fprintf (stderr, "%s:%d:%d: note: following context is `%s'\n",
- rtx_reader_ptr->get_filename (), rtx_reader_ptr->get_lineno (),
- rtx_reader_ptr->get_colno (), context);
+ md_reader_ptr->get_filename (),
+ md_reader_ptr->get_lineno (),
+ md_reader_ptr->get_colno (), context);
va_end (ap);
exit (1);
}
}
+/* Consume the next character, issuing a fatal error if it is not
+ EXPECTED. */
+
+void
+md_reader::require_char (char expected)
+{
+ int ch = read_char ();
+ if (ch != expected)
+ fatal_expected_char (expected, ch);
+}
+
/* Consume any whitespace, then consume the next non-whitespace
character, issuing a fatal error if it is not EXPECTED. */
void
-require_char_ws (char expected)
+md_reader::require_char_ws (char expected)
{
int ch = read_skip_spaces ();
if (ch != expected)
fatal_expected_char (expected, ch);
}
+/* Consume any whitespace, then consume the next word (as per read_name),
+ issuing a fatal error if it is not EXPECTED. */
+
+void
+md_reader::require_word_ws (const char *expected)
+{
+ struct md_name name;
+ read_name (&name);
+ if (strcmp (name.string, expected))
+ fatal_with_file_and_line ("missing '%s'", expected);
+}
+
/* Read the next character from the file. */
int
-rtx_reader::read_char (void)
+md_reader::read_char (void)
{
int ch;
else
m_read_md_colno++;
+ /* If we're filtering lines, treat everything before the range of
+ interest as a space, and as EOF for everything after. */
+ if (m_first_line && m_last_line)
+ {
+ if (m_read_md_lineno < m_first_line)
+ return ' ';
+ if (m_read_md_lineno > m_last_line)
+ return EOF;
+ }
+
return ch;
}
/* Put back CH, which was the last character read from the file. */
void
-rtx_reader::unread_char (int ch)
+md_reader::unread_char (int ch)
{
if (ch == '\n')
{
ungetc (ch, m_read_md_file);
}
+/* Peek at the next character from the file without consuming it. */
+
+int
+md_reader::peek_char (void)
+{
+ int ch = read_char ();
+ unread_char (ch);
+ return ch;
+}
+
/* Read an rtx code name into NAME. It is terminated by any of the
punctuation chars of rtx printed syntax. */
-void
-rtx_reader::read_name (struct md_name *name)
+bool
+md_reader::read_name_1 (struct md_name *name, file_location *out_loc)
{
int c;
size_t i;
c = read_skip_spaces ();
+ *out_loc = get_current_location ();
+
i = 0;
angle_bracket_depth = 0;
while (1)
}
if (i == 0)
- fatal_with_file_and_line ("missing name or number");
+ return false;
name->buffer[i] = 0;
name->string = name->buffer;
}
while (def);
}
+
+ return true;
+}
+
+/* Read an rtx code name into NAME. It is terminated by any of the
+ punctuation chars of rtx printed syntax. */
+
+file_location
+md_reader::read_name (struct md_name *name)
+{
+ file_location loc;
+ if (!read_name_1 (name, &loc))
+ fatal_with_file_and_line ("missing name or number");
+ return loc;
+}
+
+file_location
+md_reader::read_name_or_nil (struct md_name *name)
+{
+ file_location loc;
+ if (!read_name_1 (name, &loc))
+ {
+ file_location loc = get_current_location ();
+ read_skip_construct (0, loc);
+ /* Skip the ')'. */
+ read_char ();
+ name->buffer[0] = 0;
+ name->string = name->buffer;
+ }
+ return loc;
}
/* Subroutine of the string readers. Handles backslash escapes.
Caller has read the backslash, but not placed it into the obstack. */
void
-rtx_reader::read_escape ()
+md_reader::read_escape ()
{
int c = read_char ();
the leading quote. */
char *
-rtx_reader::read_quoted_string ()
+md_reader::read_quoted_string ()
{
int c;
the outermost braces _are_ included in the string constant. */
char *
-rtx_reader::read_braced_string ()
+md_reader::read_braced_string ()
{
int c;
int brace_depth = 1; /* caller-processed */
and dispatch to the appropriate string constant reader. */
char *
-rtx_reader::read_string (int star_if_braced)
+md_reader::read_string (int star_if_braced)
{
char *stringbuf;
int saw_paren = 0;
obstack_1grow (&m_string_obstack, '*');
stringbuf = read_braced_string ();
}
+ else if (saw_paren && c == 'n')
+ {
+ /* Handle (nil) by returning NULL. */
+ require_char ('i');
+ require_char ('l');
+ require_char_ws (')');
+ return NULL;
+ }
else
fatal_with_file_and_line ("expected `\"' or `{', found `%c'", c);
is currently nested by DEPTH levels of parentheses. */
void
-rtx_reader::read_skip_construct (int depth, file_location loc)
+md_reader::read_skip_construct (int depth, file_location loc)
{
struct md_name name;
int c;
after the "define_constants". */
void
-rtx_reader::handle_constants ()
+md_reader::handle_constants ()
{
int c;
htab_t defs;
Stop when CALLBACK returns zero. */
void
-rtx_reader::traverse_md_constants (htab_trav callback, void *info)
+md_reader::traverse_md_constants (htab_trav callback, void *info)
{
htab_traverse (get_md_constants (), callback, info);
}
directive is a define_enum rather than a define_c_enum. */
void
-rtx_reader::handle_enum (file_location loc, bool md_p)
+md_reader::handle_enum (file_location loc, bool md_p)
{
char *enum_name, *value_name;
struct md_name name;
/* Try to find the definition of the given enum. Return null on failure. */
struct enum_type *
-rtx_reader::lookup_enum_type (const char *name)
+md_reader::lookup_enum_type (const char *name)
{
return (struct enum_type *) htab_find (m_enum_types, &name);
}
returns zero. */
void
-rtx_reader::traverse_enum_types (htab_trav callback, void *info)
+md_reader::traverse_enum_types (htab_trav callback, void *info)
{
htab_traverse (m_enum_types, callback, info);
}
-/* Constructor for rtx_reader. */
+/* Constructor for md_reader. */
-rtx_reader::rtx_reader ()
-: m_toplevel_fname (NULL),
+md_reader::md_reader (bool compact)
+: m_compact (compact),
+ m_toplevel_fname (NULL),
m_base_dir (NULL),
m_read_md_file (NULL),
m_read_md_filename (NULL),
m_read_md_lineno (0),
m_read_md_colno (0),
m_first_dir_md_include (NULL),
- m_last_dir_md_include_ptr (&m_first_dir_md_include)
+ m_last_dir_md_include_ptr (&m_first_dir_md_include),
+ m_first_line (0),
+ m_last_line (0),
+ m_first_overload (NULL),
+ m_next_overload_ptr (&m_first_overload),
+ m_overloads_htab (NULL)
{
/* Set the global singleton pointer. */
- rtx_reader_ptr = this;
+ md_reader_ptr = this;
obstack_init (&m_string_obstack);
unlock_std_streams ();
}
-/* rtx_reader's destructor. */
+/* md_reader's destructor. */
-rtx_reader::~rtx_reader ()
+md_reader::~md_reader ()
{
free (m_base_dir);
obstack_free (&m_string_obstack, NULL);
/* Clear the global singleton pointer. */
- rtx_reader_ptr = NULL;
+ md_reader_ptr = NULL;
}
/* Process an "include" directive, starting with the optional space
which the "include" occurred. */
void
-rtx_reader::handle_include (file_location loc)
+md_reader::handle_include (file_location loc)
{
const char *filename;
const char *old_filename;
unknown directives. */
void
-rtx_reader::handle_file ()
+md_reader::handle_file ()
{
struct md_name directive;
int c;
and m_base_dir accordingly. */
void
-rtx_reader::handle_toplevel_file ()
+md_reader::handle_toplevel_file ()
{
const char *base;
}
file_location
-rtx_reader::get_current_location () const
+md_reader::get_current_location () const
{
return file_location (m_read_md_filename, m_read_md_lineno, m_read_md_colno);
}
/* Parse a -I option with argument ARG. */
void
-rtx_reader::add_include_path (const char *arg)
+md_reader::add_include_path (const char *arg)
{
struct file_name_list *dirtmp;
m_last_dir_md_include_ptr = &dirtmp->next;
}
+#ifdef GENERATOR_FILE
+
/* The main routine for reading .md files. Try to process all the .md
files specified on the command line and return true if no error occurred.
generic error should be reported. */
bool
-rtx_reader::read_md_files (int argc, const char **argv,
- bool (*parse_opt) (const char *))
+md_reader::read_md_files (int argc, const char **argv,
+ bool (*parse_opt) (const char *))
{
int i;
bool no_more_options;
return !have_error;
}
-/* class noop_reader : public rtx_reader */
+#endif /* #ifdef GENERATOR_FILE */
+
+/* Read FILENAME. */
+
+bool
+md_reader::read_file (const char *filename)
+{
+ m_read_md_filename = filename;
+ m_read_md_file = fopen (m_read_md_filename, "r");
+ if (m_read_md_file == 0)
+ {
+ perror (m_read_md_filename);
+ return false;
+ }
+ handle_toplevel_file ();
+ return !have_error;
+}
+
+/* Read FILENAME, filtering to just the given lines. */
+
+bool
+md_reader::read_file_fragment (const char *filename,
+ int first_line,
+ int last_line)
+{
+ m_read_md_filename = filename;
+ m_read_md_file = fopen (m_read_md_filename, "r");
+ if (m_read_md_file == 0)
+ {
+ perror (m_read_md_filename);
+ return false;
+ }
+ m_first_line = first_line;
+ m_last_line = last_line;
+ handle_toplevel_file ();
+ return !have_error;
+}
+
+/* class noop_reader : public md_reader */
/* A dummy implementation which skips unknown directives. */
void