LCOV - code coverage report
Current view: top level - gcc - read-md.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 40.2 % 567 228
Test Date: 2024-03-23 14:05:01 Functions: 40.7 % 54 22
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* MD reader for GCC.
       2                 :             :    Copyright (C) 1987-2024 Free Software Foundation, Inc.
       3                 :             : 
       4                 :             : This file is part of GCC.
       5                 :             : 
       6                 :             : GCC is free software; you can redistribute it and/or modify it under
       7                 :             : the terms of the GNU General Public License as published by the Free
       8                 :             : Software Foundation; either version 3, or (at your option) any later
       9                 :             : version.
      10                 :             : 
      11                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :             : for more details.
      15                 :             : 
      16                 :             : You should have received a copy of the GNU General Public License
      17                 :             : along with GCC; see the file COPYING3.  If not see
      18                 :             : <http://www.gnu.org/licenses/>.  */
      19                 :             : 
      20                 :             : /* This file is compiled twice: once for the generator programs
      21                 :             :    once for the compiler.  */
      22                 :             : #ifdef GENERATOR_FILE
      23                 :             : #include "bconfig.h"
      24                 :             : #else
      25                 :             : #include "config.h"
      26                 :             : #endif
      27                 :             : #include "system.h"
      28                 :             : #include "coretypes.h"
      29                 :             : #ifdef GENERATOR_FILE
      30                 :             : #include "errors.h"
      31                 :             : #endif /* #ifdef GENERATOR_FILE */
      32                 :             : #include "statistics.h"
      33                 :             : #include "vec.h"
      34                 :             : #include "read-md.h"
      35                 :             : 
      36                 :             : #ifndef GENERATOR_FILE
      37                 :             : 
      38                 :             : /* Minimal reimplementation of errors.cc for use by RTL frontend
      39                 :             :    within cc1.  */
      40                 :             : 
      41                 :             : int have_error = 0;
      42                 :             : 
      43                 :             : #endif /* #ifndef GENERATOR_FILE */
      44                 :             : 
      45                 :             : 
      46                 :             : /* This callback will be invoked whenever an md include directive is
      47                 :             :    processed.  To be used for creation of the dependency file.  */
      48                 :             : void (*include_callback) (const char *);
      49                 :             : 
      50                 :             : /* Global singleton.  */
      51                 :             : 
      52                 :             : md_reader *md_reader_ptr;
      53                 :             : 
      54                 :             : /* Given an object that starts with a char * name field, return a hash
      55                 :             :    code for its name.  */
      56                 :             : 
      57                 :             : hashval_t
      58                 :        8203 : leading_string_hash (const void *def)
      59                 :             : {
      60                 :        8203 :   return htab_hash_string (*(const char *const *) def);
      61                 :             : }
      62                 :             : 
      63                 :             : /* Given two objects that start with char * name fields, return true if
      64                 :             :    they have the same name.  */
      65                 :             : 
      66                 :             : int
      67                 :           0 : leading_string_eq_p (const void *def1, const void *def2)
      68                 :             : {
      69                 :           0 :   return strcmp (*(const char *const *) def1,
      70                 :           0 :                  *(const char *const *) def2) == 0;
      71                 :             : }
      72                 :             : 
      73                 :             : /* Return a hash value for the pointer pointed to by DEF.  */
      74                 :             : 
      75                 :             : static hashval_t
      76                 :         111 : leading_ptr_hash (const void *def)
      77                 :             : {
      78                 :         111 :   return htab_hash_pointer (*(const void *const *) def);
      79                 :             : }
      80                 :             : 
      81                 :             : /* Return true if DEF1 and DEF2 are pointers to the same pointer.  */
      82                 :             : 
      83                 :             : static int
      84                 :           0 : leading_ptr_eq_p (const void *def1, const void *def2)
      85                 :             : {
      86                 :           0 :   return *(const void *const *) def1 == *(const void *const *) def2;
      87                 :             : }
      88                 :             : 
      89                 :             : /* Associate PTR with the file position given by FILE_LOC.  */
      90                 :             : 
      91                 :             : void
      92                 :         111 : md_reader::set_md_ptr_loc (const void *ptr, file_location file_loc)
      93                 :             : {
      94                 :         111 :   struct ptr_loc *loc;
      95                 :             : 
      96                 :         111 :   loc = (struct ptr_loc *) obstack_alloc (&m_ptr_loc_obstack,
      97                 :             :                                           sizeof (struct ptr_loc));
      98                 :         111 :   loc->ptr = ptr;
      99                 :         111 :   loc->loc = file_loc;
     100                 :         111 :   *htab_find_slot (m_ptr_locs, loc, INSERT) = loc;
     101                 :         111 : }
     102                 :             : 
     103                 :             : /* Return the position associated with pointer PTR.  Return null if no
     104                 :             :    position was set.  */
     105                 :             : 
     106                 :             : const md_reader::ptr_loc *
     107                 :           0 : md_reader::get_md_ptr_loc (const void *ptr)
     108                 :             : {
     109                 :           0 :   return (const struct ptr_loc *) htab_find (m_ptr_locs, &ptr);
     110                 :             : }
     111                 :             : 
     112                 :             : /* Associate NEW_PTR with the same file position as OLD_PTR.  */
     113                 :             : 
     114                 :             : void
     115                 :           0 : md_reader::copy_md_ptr_loc (const void *new_ptr, const void *old_ptr)
     116                 :             : {
     117                 :           0 :   const struct ptr_loc *loc = get_md_ptr_loc (old_ptr);
     118                 :           0 :   if (loc != 0)
     119                 :           0 :     set_md_ptr_loc (new_ptr, loc->loc);
     120                 :           0 : }
     121                 :             : 
     122                 :             : /* If PTR is associated with a known file position, print a #line
     123                 :             :    directive for it to OUTF.  */
     124                 :             : 
     125                 :             : void
     126                 :           0 : md_reader::fprint_md_ptr_loc (FILE *outf, const void *ptr)
     127                 :             : {
     128                 :           0 :   const struct ptr_loc *loc = get_md_ptr_loc (ptr);
     129                 :           0 :   if (loc != 0)
     130                 :           0 :     fprintf (outf, "#line %d \"%s\"\n", loc->loc.lineno, loc->loc.filename);
     131                 :           0 : }
     132                 :             : 
     133                 :             : /* Special fprint_md_ptr_loc for writing to STDOUT.  */
     134                 :             : void
     135                 :           0 : md_reader::print_md_ptr_loc (const void *ptr, FILE *file)
     136                 :             : {
     137                 :           0 :   fprint_md_ptr_loc (file, ptr);
     138                 :           0 : }
     139                 :             : 
     140                 :             : /* Return a condition that satisfies both COND1 and COND2.  Either string
     141                 :             :    may be null or empty.  */
     142                 :             : 
     143                 :             : const char *
     144                 :           0 : md_reader::join_c_conditions (const char *cond1, const char *cond2)
     145                 :             : {
     146                 :           0 :   char *result;
     147                 :           0 :   const void **entry;
     148                 :             : 
     149                 :           0 :   if (cond1 == 0 || cond1[0] == 0)
     150                 :             :     return cond2;
     151                 :             : 
     152                 :           0 :   if (cond2 == 0 || cond2[0] == 0)
     153                 :             :     return cond1;
     154                 :             : 
     155                 :           0 :   if (strcmp (cond1, cond2) == 0)
     156                 :             :     return cond1;
     157                 :             : 
     158                 :           0 :   result = concat ("(", cond1, ") && (", cond2, ")", NULL);
     159                 :           0 :   obstack_ptr_grow (&m_joined_conditions_obstack, result);
     160                 :           0 :   obstack_ptr_grow (&m_joined_conditions_obstack, cond1);
     161                 :           0 :   obstack_ptr_grow (&m_joined_conditions_obstack, cond2);
     162                 :           0 :   entry = XOBFINISH (&m_joined_conditions_obstack, const void **);
     163                 :           0 :   *htab_find_slot (m_joined_conditions, entry, INSERT) = entry;
     164                 :           0 :   return result;
     165                 :             : }
     166                 :             : 
     167                 :             : /* Print condition COND to OUTF, wrapped in brackets.  If COND was created
     168                 :             :    by join_c_conditions, recursively invoke this function for the original
     169                 :             :    conditions and join the result with "&&".  Otherwise print a #line
     170                 :             :    directive for COND if its original file position is known.  */
     171                 :             : 
     172                 :             : void
     173                 :           0 : md_reader::fprint_c_condition (FILE *outf, const char *cond)
     174                 :             : {
     175                 :           0 :   const char **halves = (const char **) htab_find (m_joined_conditions, &cond);
     176                 :           0 :   if (halves != 0)
     177                 :             :     {
     178                 :           0 :       fprintf (outf, "(");
     179                 :           0 :       fprint_c_condition (outf, halves[1]);
     180                 :           0 :       fprintf (outf, " && ");
     181                 :           0 :       fprint_c_condition (outf, halves[2]);
     182                 :           0 :       fprintf (outf, ")");
     183                 :             :     }
     184                 :             :   else
     185                 :             :     {
     186                 :           0 :       fputc ('\n', outf);
     187                 :           0 :       fprint_md_ptr_loc (outf, cond);
     188                 :           0 :       fprintf (outf, "(%s)", cond);
     189                 :             :     }
     190                 :           0 : }
     191                 :             : 
     192                 :             : /* Special fprint_c_condition for writing to STDOUT.  */
     193                 :             : 
     194                 :             : void
     195                 :           0 : md_reader::print_c_condition (const char *cond)
     196                 :             : {
     197                 :           0 :   fprint_c_condition (stdout, cond);
     198                 :           0 : }
     199                 :             : 
     200                 :             : /* A vfprintf-like function for reporting an error against line LINENO
     201                 :             :    of the current MD file.  */
     202                 :             : 
     203                 :             : static void ATTRIBUTE_PRINTF(2,0)
     204                 :           0 : message_at_1 (file_location loc, const char *msg, va_list ap)
     205                 :             : {
     206                 :           0 :   fprintf (stderr, "%s:%d:%d: ", loc.filename, loc.lineno, loc.colno);
     207                 :           0 :   vfprintf (stderr, msg, ap);
     208                 :           0 :   fputc ('\n', stderr);
     209                 :           0 : }
     210                 :             : 
     211                 :             : /* A printf-like function for reporting a message against location LOC.  */
     212                 :             : 
     213                 :             : void
     214                 :           0 : message_at (file_location loc, const char *msg, ...)
     215                 :             : {
     216                 :           0 :   va_list ap;
     217                 :             : 
     218                 :           0 :   va_start (ap, msg);
     219                 :           0 :   message_at_1 (loc, msg, ap);
     220                 :           0 :   va_end (ap);
     221                 :           0 : }
     222                 :             : 
     223                 :             : /* Like message_at, but treat the condition as an error.  */
     224                 :             : 
     225                 :             : void
     226                 :           0 : error_at (file_location loc, const char *msg, ...)
     227                 :             : {
     228                 :           0 :   va_list ap;
     229                 :             : 
     230                 :           0 :   va_start (ap, msg);
     231                 :           0 :   message_at_1 (loc, msg, ap);
     232                 :           0 :   va_end (ap);
     233                 :           0 :   have_error = 1;
     234                 :           0 : }
     235                 :             : 
     236                 :             : /* Like message_at, but treat the condition as a fatal error.  */
     237                 :             : 
     238                 :             : void
     239                 :           0 : fatal_at (file_location loc, const char *msg, ...)
     240                 :             : {
     241                 :           0 :   va_list ap;
     242                 :             : 
     243                 :           0 :   va_start (ap, msg);
     244                 :           0 :   message_at_1 (loc, msg, ap);
     245                 :           0 :   va_end (ap);
     246                 :           0 :   exit (1);
     247                 :             : }
     248                 :             : 
     249                 :             : /* A printf-like function for reporting an error against the current
     250                 :             :    position in the MD file.  */
     251                 :             : 
     252                 :             : void
     253                 :           1 : fatal_with_file_and_line (const char *msg, ...)
     254                 :             : {
     255                 :           1 :   char context[64];
     256                 :           1 :   size_t i;
     257                 :           1 :   int c;
     258                 :           1 :   va_list ap;
     259                 :             : 
     260                 :           1 :   va_start (ap, msg);
     261                 :             : 
     262                 :           1 :   fprintf (stderr, "%s:%d:%d: error: ", md_reader_ptr->get_filename (),
     263                 :             :            md_reader_ptr->get_lineno (),
     264                 :             :            md_reader_ptr->get_colno ());
     265                 :           1 :   vfprintf (stderr, msg, ap);
     266                 :           1 :   putc ('\n', stderr);
     267                 :             : 
     268                 :             :   /* Gather some following context.  */
     269                 :          43 :   for (i = 0; i < sizeof (context)-1; ++i)
     270                 :             :     {
     271                 :          42 :       c = read_char ();
     272                 :          42 :       if (c == EOF)
     273                 :             :         break;
     274                 :          42 :       if (c == '\r' || c == '\n')
     275                 :             :         {
     276                 :           1 :           unread_char (c);
     277                 :           1 :           break;
     278                 :             :         }
     279                 :          41 :       context[i] = c;
     280                 :             :     }
     281                 :           1 :   context[i] = '\0';
     282                 :             : 
     283                 :           1 :   fprintf (stderr, "%s:%d:%d: note: following context is `%s'\n",
     284                 :             :            md_reader_ptr->get_filename (),
     285                 :             :            md_reader_ptr->get_lineno (),
     286                 :             :            md_reader_ptr->get_colno (), context);
     287                 :             : 
     288                 :           1 :   va_end (ap);
     289                 :           1 :   exit (1);
     290                 :             : }
     291                 :             : 
     292                 :             : /* Report that we found character ACTUAL when we expected to find
     293                 :             :    character EXPECTED.  */
     294                 :             : 
     295                 :             : void
     296                 :           0 : fatal_expected_char (int expected, int actual)
     297                 :             : {
     298                 :           0 :   if (actual == EOF)
     299                 :           0 :     fatal_with_file_and_line ("expected character `%c', found EOF",
     300                 :             :                               expected);
     301                 :             :   else
     302                 :           0 :     fatal_with_file_and_line ("expected character `%c', found `%c'",
     303                 :             :                               expected, actual);
     304                 :             : }
     305                 :             : 
     306                 :             : /* Read chars from the MD file until a non-whitespace char and return that.
     307                 :             :    Comments, both Lisp style and C style, are treated as whitespace.  */
     308                 :             : 
     309                 :             : int
     310                 :       19713 : read_skip_spaces (void)
     311                 :             : {
     312                 :       49666 :   int c;
     313                 :             : 
     314                 :       49666 :   while (1)
     315                 :             :     {
     316                 :       49666 :       c = read_char ();
     317                 :       49666 :       switch (c)
     318                 :             :         {
     319                 :             :         case ' ': case '\t': case '\f': case '\r': case '\n':
     320                 :             :           break;
     321                 :             : 
     322                 :        5390 :         case ';':
     323                 :        5390 :           do
     324                 :        5390 :             c = read_char ();
     325                 :        5390 :           while (c != '\n' && c != EOF);
     326                 :             :           break;
     327                 :             : 
     328                 :           4 :         case '/':
     329                 :           4 :           {
     330                 :           4 :             int prevc;
     331                 :           4 :             c = read_char ();
     332                 :           4 :             if (c != '*')
     333                 :             :               {
     334                 :           0 :                 unread_char (c);
     335                 :           0 :                 fatal_with_file_and_line ("stray '/' in file");
     336                 :             :               }
     337                 :             : 
     338                 :             :             prevc = 0;
     339                 :         580 :             while ((c = read_char ()) && c != EOF)
     340                 :             :               {
     341                 :         580 :                 if (prevc == '*' && c == '/')
     342                 :             :                   break;
     343                 :             :                 prevc = c;
     344                 :             :               }
     345                 :             :           }
     346                 :             :           break;
     347                 :             : 
     348                 :       19713 :         default:
     349                 :       19713 :           return c;
     350                 :             :         }
     351                 :             :     }
     352                 :             : }
     353                 :             : 
     354                 :             : /* Consume the next character, issuing a fatal error if it is not
     355                 :             :    EXPECTED.  */
     356                 :             : 
     357                 :             : void
     358                 :         562 : md_reader::require_char (char expected)
     359                 :             : {
     360                 :         562 :   int ch = read_char ();
     361                 :         562 :   if (ch != expected)
     362                 :           0 :     fatal_expected_char (expected, ch);
     363                 :         562 : }
     364                 :             : 
     365                 :             : /* Consume any whitespace, then consume the next non-whitespace
     366                 :             :    character, issuing a fatal error if it is not EXPECTED.  */
     367                 :             : 
     368                 :             : void
     369                 :        5082 : md_reader::require_char_ws (char expected)
     370                 :             : {
     371                 :        5082 :   int ch = read_skip_spaces ();
     372                 :        5082 :   if (ch != expected)
     373                 :           0 :     fatal_expected_char (expected, ch);
     374                 :        5082 : }
     375                 :             : 
     376                 :             : /* Consume any whitespace, then consume the next word (as per read_name),
     377                 :             :    issuing a fatal error if it is not EXPECTED.  */
     378                 :             : 
     379                 :             : void
     380                 :         279 : md_reader::require_word_ws (const char *expected)
     381                 :             : {
     382                 :         279 :   struct md_name name;
     383                 :         279 :   read_name (&name);
     384                 :         279 :   if (strcmp (name.string, expected))
     385                 :           0 :     fatal_with_file_and_line ("missing '%s'", expected);
     386                 :         279 : }
     387                 :             : 
     388                 :             : /* Read the next character from the file.  */
     389                 :             : 
     390                 :             : int
     391                 :      101516 : md_reader::read_char (void)
     392                 :             : {
     393                 :      101516 :   int ch;
     394                 :             : 
     395                 :      101516 :   ch = getc (m_read_md_file);
     396                 :      101516 :   if (ch == '\n')
     397                 :             :     {
     398                 :        2971 :       m_read_md_lineno++;
     399                 :        2971 :       m_last_line_colno = m_read_md_colno;
     400                 :        2971 :       m_read_md_colno = 0;
     401                 :             :     }
     402                 :             :   else
     403                 :       98545 :     m_read_md_colno++;
     404                 :             : 
     405                 :             :   /* If we're filtering lines, treat everything before the range of
     406                 :             :      interest as a space, and as EOF for everything after.  */
     407                 :      101516 :   if (m_first_line && m_last_line)
     408                 :             :     {
     409                 :       60720 :       if (m_read_md_lineno < m_first_line)
     410                 :             :         return ' ';
     411                 :       53493 :       if (m_read_md_lineno > m_last_line)
     412                 :          31 :         return EOF;
     413                 :             :     }
     414                 :             : 
     415                 :             :   return ch;
     416                 :             : }
     417                 :             : 
     418                 :             : /* Put back CH, which was the last character read from the file.  */
     419                 :             : 
     420                 :             : void
     421                 :       11280 : md_reader::unread_char (int ch)
     422                 :             : {
     423                 :       11280 :   if (ch == '\n')
     424                 :             :     {
     425                 :         440 :       m_read_md_lineno--;
     426                 :         440 :       m_read_md_colno = m_last_line_colno;
     427                 :             :     }
     428                 :             :   else
     429                 :       10840 :     m_read_md_colno--;
     430                 :       11280 :   ungetc (ch, m_read_md_file);
     431                 :       11280 : }
     432                 :             : 
     433                 :             : /* Peek at the next character from the file without consuming it.  */
     434                 :             : 
     435                 :             : int
     436                 :        2132 : md_reader::peek_char (void)
     437                 :             : {
     438                 :        2132 :   int ch = read_char ();
     439                 :        2132 :   unread_char (ch);
     440                 :        2132 :   return ch;
     441                 :             : }
     442                 :             : 
     443                 :             : /* Read an rtx code name into NAME.  It is terminated by any of the
     444                 :             :    punctuation chars of rtx printed syntax.  */
     445                 :             : 
     446                 :             : bool
     447                 :        6748 : md_reader::read_name_1 (struct md_name *name, file_location *out_loc)
     448                 :             : {
     449                 :        6748 :   int c;
     450                 :        6748 :   size_t i;
     451                 :        6748 :   int angle_bracket_depth;
     452                 :             : 
     453                 :        6748 :   c = read_skip_spaces ();
     454                 :             : 
     455                 :        6748 :   *out_loc = get_current_location ();
     456                 :             : 
     457                 :        6748 :   i = 0;
     458                 :        6748 :   angle_bracket_depth = 0;
     459                 :       60478 :   while (1)
     460                 :             :     {
     461                 :       33613 :       if (c == '<')
     462                 :         242 :         angle_bracket_depth++;
     463                 :             : 
     464                 :       33613 :       if ((c == '>') && (angle_bracket_depth > 0))
     465                 :         242 :           angle_bracket_depth--;
     466                 :             : 
     467                 :       33613 :       if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r'
     468                 :             :           || c == EOF)
     469                 :             :         break;
     470                 :       29212 :       if (angle_bracket_depth == 0)
     471                 :             :         {
     472                 :       28702 :           if (c == ':' || c == ')' || c == ']'
     473                 :             :               || c == '"' || c == '/' || c == '(' || c == '[')
     474                 :             :             {
     475                 :        2347 :               unread_char (c);
     476                 :        2347 :               break;
     477                 :             :             }
     478                 :             :         }
     479                 :             : 
     480                 :       26865 :       if (i == sizeof (name->buffer) - 1)
     481                 :           0 :         fatal_with_file_and_line ("name too long");
     482                 :       26865 :       name->buffer[i++] = c;
     483                 :             : 
     484                 :       26865 :       c = read_char ();
     485                 :             :     }
     486                 :             : 
     487                 :        6748 :   if (i == 0)
     488                 :             :     return false;
     489                 :             : 
     490                 :        6748 :   name->buffer[i] = 0;
     491                 :        6748 :   name->string = name->buffer;
     492                 :             : 
     493                 :        6748 :   if (m_md_constants)
     494                 :             :     {
     495                 :             :       /* Do constant expansion.  */
     496                 :        6748 :       struct md_constant *def;
     497                 :             : 
     498                 :        6748 :       do
     499                 :             :         {
     500                 :        6748 :           struct md_constant tmp_def;
     501                 :             : 
     502                 :        6748 :           tmp_def.name = name->string;
     503                 :        6748 :           def = (struct md_constant *) htab_find (m_md_constants, &tmp_def);
     504                 :        6748 :           if (def)
     505                 :           0 :             name->string = def->value;
     506                 :             :         }
     507                 :        6748 :       while (def);
     508                 :             :     }
     509                 :             : 
     510                 :             :   return true;
     511                 :             : }
     512                 :             : 
     513                 :             : /* Read an rtx code name into NAME.  It is terminated by any of the
     514                 :             :    punctuation chars of rtx printed syntax.  */
     515                 :             : 
     516                 :             : file_location
     517                 :        6748 : md_reader::read_name (struct md_name *name)
     518                 :             : {
     519                 :        6748 :   file_location loc;
     520                 :        6748 :   if (!read_name_1 (name, &loc))
     521                 :           0 :     fatal_with_file_and_line ("missing name or number");
     522                 :        6748 :   return loc;
     523                 :             : }
     524                 :             : 
     525                 :             : file_location
     526                 :           0 : md_reader::read_name_or_nil (struct md_name *name)
     527                 :             : {
     528                 :           0 :   file_location loc;
     529                 :           0 :   if (!read_name_1 (name, &loc))
     530                 :             :     {
     531                 :           0 :       file_location loc = get_current_location ();
     532                 :           0 :       read_skip_construct (0, loc);
     533                 :             :       /* Skip the ')'.  */
     534                 :           0 :       read_char ();
     535                 :           0 :       name->buffer[0] = 0;
     536                 :           0 :       name->string = name->buffer;
     537                 :             :     }
     538                 :           0 :   return loc;
     539                 :             : }
     540                 :             : 
     541                 :             : /* Subroutine of the string readers.  Handles backslash escapes.
     542                 :             :    Caller has read the backslash, but not placed it into the obstack.  */
     543                 :             : 
     544                 :             : void
     545                 :           0 : md_reader::read_escape ()
     546                 :             : {
     547                 :           0 :   int c = read_char ();
     548                 :             : 
     549                 :           0 :   switch (c)
     550                 :             :     {
     551                 :             :       /* Backslash-newline is replaced by nothing, as in C.  */
     552                 :             :     case '\n':
     553                 :             :       return;
     554                 :             : 
     555                 :             :       /* \" \' \\ are replaced by the second character.  */
     556                 :             :     case '\\':
     557                 :             :     case '"':
     558                 :             :     case '\'':
     559                 :             :       break;
     560                 :             : 
     561                 :             :       /* Standard C string escapes:
     562                 :             :          \a \b \f \n \r \t \v
     563                 :             :          \[0-7] \x
     564                 :             :          all are passed through to the output string unmolested.
     565                 :             :          In normal use these wind up in a string constant processed
     566                 :             :          by the C compiler, which will translate them appropriately.
     567                 :             :          We do not bother checking that \[0-7] are followed by up to
     568                 :             :          two octal digits, or that \x is followed by N hex digits.
     569                 :             :          \? \u \U are left out because they are not in traditional C.  */
     570                 :           0 :     case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
     571                 :           0 :     case '0': case '1': case '2': case '3': case '4': case '5': case '6':
     572                 :           0 :     case '7': case 'x':
     573                 :           0 :       obstack_1grow (&m_string_obstack, '\\');
     574                 :           0 :       break;
     575                 :             : 
     576                 :             :       /* \; makes stuff for a C string constant containing
     577                 :             :          newline and tab.  */
     578                 :           0 :     case ';':
     579                 :           0 :       obstack_grow (&m_string_obstack, "\\n\\t", 4);
     580                 :           0 :       return;
     581                 :             : 
     582                 :             :       /* pass anything else through, but issue a warning.  */
     583                 :           0 :     default:
     584                 :           0 :       fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n",
     585                 :             :                get_filename (), get_lineno (),
     586                 :             :                c);
     587                 :           0 :       obstack_1grow (&m_string_obstack, '\\');
     588                 :           0 :       break;
     589                 :             :     }
     590                 :             : 
     591                 :           0 :   obstack_1grow (&m_string_obstack, c);
     592                 :             : }
     593                 :             : 
     594                 :             : /* Read a double-quoted string onto the obstack.  Caller has scanned
     595                 :             :    the leading quote.  */
     596                 :             : 
     597                 :             : char *
     598                 :         584 : md_reader::read_quoted_string ()
     599                 :             : {
     600                 :       11494 :   int c;
     601                 :             : 
     602                 :       11494 :   while (1)
     603                 :             :     {
     604                 :       11494 :       c = read_char (); /* Read the string  */
     605                 :       11494 :       if (c == '\\')
     606                 :             :         {
     607                 :           0 :           read_escape ();
     608                 :           0 :           continue;
     609                 :             :         }
     610                 :       11494 :       else if (c == '"' || c == EOF)
     611                 :             :         break;
     612                 :             : 
     613                 :       10910 :       obstack_1grow (&m_string_obstack, c);
     614                 :             :     }
     615                 :             : 
     616                 :         584 :   obstack_1grow (&m_string_obstack, 0);
     617                 :         584 :   return XOBFINISH (&m_string_obstack, char *);
     618                 :             : }
     619                 :             : 
     620                 :             : /* Read a braced string (a la Tcl) onto the string obstack.  Caller
     621                 :             :    has scanned the leading brace.  Note that unlike quoted strings,
     622                 :             :    the outermost braces _are_ included in the string constant.  */
     623                 :             : 
     624                 :             : char *
     625                 :           0 : md_reader::read_braced_string ()
     626                 :             : {
     627                 :           0 :   int c;
     628                 :           0 :   int brace_depth = 1;  /* caller-processed */
     629                 :           0 :   unsigned long starting_read_md_lineno = get_lineno ();
     630                 :             : 
     631                 :           0 :   obstack_1grow (&m_string_obstack, '{');
     632                 :           0 :   while (brace_depth)
     633                 :             :     {
     634                 :           0 :       c = read_char (); /* Read the string  */
     635                 :             : 
     636                 :           0 :       if (c == '{')
     637                 :           0 :         brace_depth++;
     638                 :           0 :       else if (c == '}')
     639                 :           0 :         brace_depth--;
     640                 :           0 :       else if (c == '\\')
     641                 :             :         {
     642                 :           0 :           read_escape ();
     643                 :           0 :           continue;
     644                 :             :         }
     645                 :           0 :       else if (c == EOF)
     646                 :           0 :         fatal_with_file_and_line
     647                 :           0 :           ("missing closing } for opening brace on line %lu",
     648                 :             :            starting_read_md_lineno);
     649                 :             : 
     650                 :           0 :       obstack_1grow (&m_string_obstack, c);
     651                 :             :     }
     652                 :             : 
     653                 :           0 :   obstack_1grow (&m_string_obstack, 0);
     654                 :           0 :   return XOBFINISH (&m_string_obstack, char *);
     655                 :             : }
     656                 :             : 
     657                 :             : /* Read some kind of string constant.  This is the high-level routine
     658                 :             :    used by read_rtx.  It handles surrounding parentheses, leading star,
     659                 :             :    and dispatch to the appropriate string constant reader.  */
     660                 :             : 
     661                 :             : char *
     662                 :         119 : md_reader::read_string (int star_if_braced)
     663                 :             : {
     664                 :         119 :   char *stringbuf;
     665                 :         119 :   int saw_paren = 0;
     666                 :         119 :   int c;
     667                 :             : 
     668                 :         119 :   c = read_skip_spaces ();
     669                 :         119 :   if (c == '(')
     670                 :             :     {
     671                 :          26 :       saw_paren = 1;
     672                 :          26 :       c = read_skip_spaces ();
     673                 :             :     }
     674                 :             : 
     675                 :         119 :   file_location loc = get_current_location ();
     676                 :         119 :   if (c == '"')
     677                 :         111 :     stringbuf = read_quoted_string ();
     678                 :           8 :   else if (c == '{')
     679                 :             :     {
     680                 :           0 :       if (star_if_braced)
     681                 :           0 :         obstack_1grow (&m_string_obstack, '*');
     682                 :           0 :       stringbuf = read_braced_string ();
     683                 :             :     }
     684                 :           8 :   else if (saw_paren && c == 'n')
     685                 :             :     {
     686                 :             :       /* Handle (nil) by returning NULL.  */
     687                 :           8 :       require_char ('i');
     688                 :           8 :       require_char ('l');
     689                 :           8 :       require_char_ws (')');
     690                 :           8 :       return NULL;
     691                 :             :     }
     692                 :             :   else
     693                 :           0 :     fatal_with_file_and_line ("expected `\"' or `{', found `%c'", c);
     694                 :             : 
     695                 :         111 :   if (saw_paren)
     696                 :          18 :     require_char_ws (')');
     697                 :             : 
     698                 :         111 :   set_md_ptr_loc (stringbuf, loc);
     699                 :         111 :   return stringbuf;
     700                 :             : }
     701                 :             : 
     702                 :             : /* Skip the rest of a construct that started at line LINENO and that
     703                 :             :    is currently nested by DEPTH levels of parentheses.  */
     704                 :             : 
     705                 :             : void
     706                 :           0 : md_reader::read_skip_construct (int depth, file_location loc)
     707                 :             : {
     708                 :           0 :   struct md_name name;
     709                 :           0 :   int c;
     710                 :             : 
     711                 :           0 :   do
     712                 :             :     {
     713                 :           0 :       c = read_skip_spaces ();
     714                 :           0 :       if (c == EOF)
     715                 :             :         {
     716                 :           0 :           error_at (loc, "unterminated construct");
     717                 :           0 :           exit (1);
     718                 :             :         }
     719                 :           0 :       switch (c)
     720                 :             :         {
     721                 :           0 :         case '(':
     722                 :           0 :           depth++;
     723                 :           0 :           break;
     724                 :             : 
     725                 :           0 :         case ')':
     726                 :           0 :           depth--;
     727                 :           0 :           break;
     728                 :             : 
     729                 :             :         case ':':
     730                 :             :         case '[':
     731                 :             :         case ']':
     732                 :             :         case '/':
     733                 :             :           break;
     734                 :             : 
     735                 :           0 :         case '\"':
     736                 :           0 :         case '{':
     737                 :           0 :           unread_char (c);
     738                 :           0 :           read_string (false);
     739                 :           0 :           break;
     740                 :             : 
     741                 :           0 :         default:
     742                 :           0 :           unread_char (c);
     743                 :           0 :           read_name (&name);
     744                 :           0 :           break;
     745                 :             :         }
     746                 :             :     }
     747                 :           0 :   while (depth > 0);
     748                 :           0 :   unread_char (c);
     749                 :           0 : }
     750                 :             : 
     751                 :             : /* Given a string, return the number of comma-separated elements in it.
     752                 :             :    Return 0 for the null string.  */
     753                 :             : 
     754                 :             : int
     755                 :           0 : n_comma_elts (const char *s)
     756                 :             : {
     757                 :           0 :   int n;
     758                 :             : 
     759                 :           0 :   if (*s == '\0')
     760                 :             :     return 0;
     761                 :             : 
     762                 :           0 :   for (n = 1; *s; s++)
     763                 :           0 :     if (*s == ',')
     764                 :           0 :       n++;
     765                 :             : 
     766                 :             :   return n;
     767                 :             : }
     768                 :             : 
     769                 :             : /* Given a pointer to a (char *), return a pointer to the beginning of the
     770                 :             :    next comma-separated element in the string.  Advance the pointer given
     771                 :             :    to the end of that element.  Return NULL if at end of string.  Caller
     772                 :             :    is responsible for copying the string if necessary.  White space between
     773                 :             :    a comma and an element is ignored.  */
     774                 :             : 
     775                 :             : const char *
     776                 :           0 : scan_comma_elt (const char **pstr)
     777                 :             : {
     778                 :           0 :   const char *start;
     779                 :           0 :   const char *p = *pstr;
     780                 :             : 
     781                 :           0 :   if (*p == ',')
     782                 :           0 :     p++;
     783                 :           0 :   while (ISSPACE (*p))
     784                 :           0 :     p++;
     785                 :             : 
     786                 :           0 :   if (*p == '\0')
     787                 :             :     return NULL;
     788                 :             : 
     789                 :             :   start = p;
     790                 :             : 
     791                 :           0 :   while (*p != ',' && *p != '\0')
     792                 :           0 :     p++;
     793                 :             : 
     794                 :           0 :   *pstr = p;
     795                 :           0 :   return start;
     796                 :             : }
     797                 :             : 
     798                 :             : /* Convert STRING to uppercase.  */
     799                 :             : 
     800                 :             : void
     801                 :           0 : upcase_string (char *string)
     802                 :             : {
     803                 :           0 :   int i;
     804                 :             : 
     805                 :           0 :   for (i = 0; string[i]; i++)
     806                 :           0 :     string[i] = TOUPPER (string[i]);
     807                 :           0 : }
     808                 :             : 
     809                 :             : /* Add a NAME = VALUE definition to md_constants-style hash table DEFS,
     810                 :             :    where both NAME and VALUE are malloc()ed strings.  PARENT_ENUM is the
     811                 :             :    enum to which NAME belongs, or null if NAME is a stand-alone constant.  */
     812                 :             : 
     813                 :             : static struct md_constant *
     814                 :           0 : add_constant (htab_t defs, char *name, char *value,
     815                 :             :               struct enum_type *parent_enum)
     816                 :             : {
     817                 :           0 :   struct md_constant *def, tmp_def;
     818                 :           0 :   void **entry_ptr;
     819                 :             : 
     820                 :           0 :   tmp_def.name = name;
     821                 :           0 :   entry_ptr = htab_find_slot (defs, &tmp_def, INSERT);
     822                 :           0 :   if (*entry_ptr)
     823                 :             :     {
     824                 :           0 :       def = (struct md_constant *) *entry_ptr;
     825                 :           0 :       if (strcmp (def->value, value) != 0)
     826                 :           0 :         fatal_with_file_and_line ("redefinition of `%s', was `%s', now `%s'",
     827                 :             :                                   def->name, def->value, value);
     828                 :           0 :       else if (parent_enum || def->parent_enum)
     829                 :           0 :         fatal_with_file_and_line ("redefinition of `%s'", def->name);
     830                 :           0 :       free (name);
     831                 :           0 :       free (value);
     832                 :             :     }
     833                 :             :   else
     834                 :             :     {
     835                 :           0 :       def = XNEW (struct md_constant);
     836                 :           0 :       def->name = name;
     837                 :           0 :       def->value = value;
     838                 :           0 :       def->parent_enum = parent_enum;
     839                 :           0 :       *entry_ptr = def;
     840                 :             :     }
     841                 :           0 :   return def;
     842                 :             : }
     843                 :             : 
     844                 :             : /* Process a define_constants directive, starting with the optional space
     845                 :             :    after the "define_constants".  */
     846                 :             : 
     847                 :             : void
     848                 :           0 : md_reader::handle_constants ()
     849                 :             : {
     850                 :           0 :   int c;
     851                 :           0 :   htab_t defs;
     852                 :             : 
     853                 :           0 :   require_char_ws ('[');
     854                 :             : 
     855                 :             :   /* Disable constant expansion during definition processing.  */
     856                 :           0 :   defs = m_md_constants;
     857                 :           0 :   m_md_constants = 0;
     858                 :           0 :   while ( (c = read_skip_spaces ()) != ']')
     859                 :             :     {
     860                 :           0 :       struct md_name name, value;
     861                 :             : 
     862                 :           0 :       if (c != '(')
     863                 :           0 :         fatal_expected_char ('(', c);
     864                 :             : 
     865                 :           0 :       read_name (&name);
     866                 :           0 :       read_name (&value);
     867                 :           0 :       add_constant (defs, xstrdup (name.string), xstrdup (value.string), 0);
     868                 :             : 
     869                 :           0 :       require_char_ws (')');
     870                 :             :     }
     871                 :           0 :   m_md_constants = defs;
     872                 :           0 : }
     873                 :             : 
     874                 :             : /* For every constant definition, call CALLBACK with two arguments:
     875                 :             :    a pointer a pointer to the constant definition and INFO.
     876                 :             :    Stop when CALLBACK returns zero.  */
     877                 :             : 
     878                 :             : void
     879                 :           0 : md_reader::traverse_md_constants (htab_trav callback, void *info)
     880                 :             : {
     881                 :           0 :   htab_traverse (get_md_constants (), callback, info);
     882                 :           0 : }
     883                 :             : 
     884                 :             : /* Return a malloc()ed decimal string that represents number NUMBER.  */
     885                 :             : 
     886                 :             : static char *
     887                 :           0 : md_decimal_string (int number)
     888                 :             : {
     889                 :             :   /* A safe overestimate.  +1 for sign, +1 for null terminator.  */
     890                 :           0 :   char buffer[sizeof (int) * CHAR_BIT + 1 + 1];
     891                 :             : 
     892                 :           0 :   sprintf (buffer, "%d", number);
     893                 :           0 :   return xstrdup (buffer);
     894                 :             : }
     895                 :             : 
     896                 :             : /* Process a define_enum or define_c_enum directive, starting with
     897                 :             :    the optional space after the "define_enum".  LINENO is the line
     898                 :             :    number on which the directive started and MD_P is true if the
     899                 :             :    directive is a define_enum rather than a define_c_enum.  */
     900                 :             : 
     901                 :             : void
     902                 :           0 : md_reader::handle_enum (file_location loc, bool md_p)
     903                 :             : {
     904                 :           0 :   char *enum_name, *value_name;
     905                 :           0 :   unsigned int cur_value;
     906                 :           0 :   struct md_name name, value;
     907                 :           0 :   struct enum_type *def;
     908                 :           0 :   struct enum_value *ev;
     909                 :           0 :   void **slot;
     910                 :           0 :   int c;
     911                 :             : 
     912                 :           0 :   enum_name = read_string (false);
     913                 :           0 :   slot = htab_find_slot (m_enum_types, &enum_name, INSERT);
     914                 :           0 :   if (*slot)
     915                 :             :     {
     916                 :           0 :       def = (struct enum_type *) *slot;
     917                 :           0 :       if (def->md_p != md_p)
     918                 :           0 :         error_at (loc, "redefining `%s' as a different type of enum",
     919                 :             :                   enum_name);
     920                 :             :     }
     921                 :             :   else
     922                 :             :     {
     923                 :           0 :       def = XNEW (struct enum_type);
     924                 :           0 :       def->name = enum_name;
     925                 :           0 :       def->md_p = md_p;
     926                 :           0 :       def->values = 0;
     927                 :           0 :       def->tail_ptr = &def->values;
     928                 :           0 :       def->num_values = 0;
     929                 :           0 :       *slot = def;
     930                 :             :     }
     931                 :             : 
     932                 :           0 :   cur_value = def->num_values;
     933                 :           0 :   require_char_ws ('[');
     934                 :             : 
     935                 :           0 :   while ((c = read_skip_spaces ()) != ']')
     936                 :             :     {
     937                 :           0 :       if (c == EOF)
     938                 :             :         {
     939                 :           0 :           error_at (loc, "unterminated construct");
     940                 :           0 :           exit (1);
     941                 :             :         }
     942                 :           0 :       if (c == '(')
     943                 :             :         {
     944                 :           0 :           read_name (&name);
     945                 :           0 :           read_name (&value);
     946                 :           0 :           require_char_ws (')');
     947                 :           0 :           cur_value = atoi (value.string);
     948                 :             :         }
     949                 :             :       else
     950                 :             :         {
     951                 :           0 :           unread_char (c);
     952                 :           0 :           read_name (&name);
     953                 :             :         }
     954                 :             : 
     955                 :           0 :       ev = XNEW (struct enum_value);
     956                 :           0 :       ev->next = 0;
     957                 :           0 :       if (md_p)
     958                 :             :         {
     959                 :           0 :           value_name = concat (def->name, "_", name.string, NULL);
     960                 :           0 :           upcase_string (value_name);
     961                 :           0 :           ev->name = xstrdup (name.string);
     962                 :             :         }
     963                 :             :       else
     964                 :             :         {
     965                 :           0 :           value_name = xstrdup (name.string);
     966                 :           0 :           ev->name = value_name;
     967                 :             :         }
     968                 :           0 :       ev->def = add_constant (get_md_constants (), value_name,
     969                 :             :                               md_decimal_string (cur_value), def);
     970                 :             : 
     971                 :           0 :       *def->tail_ptr = ev;
     972                 :           0 :       def->tail_ptr = &ev->next;
     973                 :           0 :       def->num_values++;
     974                 :           0 :       cur_value++;
     975                 :             :     }
     976                 :           0 : }
     977                 :             : 
     978                 :             : /* Try to find the definition of the given enum.  Return null on failure.  */
     979                 :             : 
     980                 :             : struct enum_type *
     981                 :           0 : md_reader::lookup_enum_type (const char *name)
     982                 :             : {
     983                 :           0 :   return (struct enum_type *) htab_find (m_enum_types, &name);
     984                 :             : }
     985                 :             : 
     986                 :             : /* For every enum definition, call CALLBACK with two arguments:
     987                 :             :    a pointer to the constant definition and INFO.  Stop when CALLBACK
     988                 :             :    returns zero.  */
     989                 :             : 
     990                 :             : void
     991                 :           0 : md_reader::traverse_enum_types (htab_trav callback, void *info)
     992                 :             : {
     993                 :           0 :   htab_traverse (m_enum_types, callback, info);
     994                 :           0 : }
     995                 :             : 
     996                 :             : 
     997                 :             : /* Constructor for md_reader.  */
     998                 :             : 
     999                 :          93 : md_reader::md_reader (bool compact)
    1000                 :          93 : : m_compact (compact),
    1001                 :          93 :   m_toplevel_fname (NULL),
    1002                 :          93 :   m_base_dir (NULL),
    1003                 :          93 :   m_read_md_file (NULL),
    1004                 :          93 :   m_read_md_filename (NULL),
    1005                 :          93 :   m_read_md_lineno (0),
    1006                 :          93 :   m_read_md_colno (0),
    1007                 :          93 :   m_first_dir_md_include (NULL),
    1008                 :          93 :   m_last_dir_md_include_ptr (&m_first_dir_md_include),
    1009                 :          93 :   m_first_line (0),
    1010                 :          93 :   m_last_line (0),
    1011                 :          93 :   m_first_overload (NULL),
    1012                 :          93 :   m_next_overload_ptr (&m_first_overload),
    1013                 :          93 :   m_overloads_htab (NULL)
    1014                 :             : {
    1015                 :             :   /* Set the global singleton pointer.  */
    1016                 :          93 :   md_reader_ptr = this;
    1017                 :             : 
    1018                 :          93 :   obstack_init (&m_string_obstack);
    1019                 :             : 
    1020                 :          93 :   m_ptr_locs = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
    1021                 :          93 :   obstack_init (&m_ptr_loc_obstack);
    1022                 :             : 
    1023                 :          93 :   m_joined_conditions = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
    1024                 :          93 :   obstack_init (&m_joined_conditions_obstack);
    1025                 :             : 
    1026                 :          93 :   m_md_constants = htab_create (31, leading_string_hash,
    1027                 :             :                                 leading_string_eq_p, (htab_del) 0);
    1028                 :             : 
    1029                 :          93 :   m_enum_types = htab_create (31, leading_string_hash,
    1030                 :             :                               leading_string_eq_p, (htab_del) 0);
    1031                 :             : 
    1032                 :             :   /* Unlock the stdio streams.  */
    1033                 :          93 :   unlock_std_streams ();
    1034                 :          93 : }
    1035                 :             : 
    1036                 :             : /* md_reader's destructor.  */
    1037                 :             : 
    1038                 :          92 : md_reader::~md_reader ()
    1039                 :             : {
    1040                 :          92 :   free (m_base_dir);
    1041                 :             : 
    1042                 :          92 :   htab_delete (m_enum_types);
    1043                 :             : 
    1044                 :          92 :   htab_delete (m_md_constants);
    1045                 :             : 
    1046                 :          92 :   obstack_free (&m_joined_conditions_obstack, NULL);
    1047                 :          92 :   htab_delete (m_joined_conditions);
    1048                 :             : 
    1049                 :          92 :   obstack_free (&m_ptr_loc_obstack, NULL);
    1050                 :          92 :   htab_delete (m_ptr_locs);
    1051                 :             : 
    1052                 :          92 :   obstack_free (&m_string_obstack, NULL);
    1053                 :             : 
    1054                 :             :   /* Clear the global singleton pointer.  */
    1055                 :          92 :   md_reader_ptr = NULL;
    1056                 :          92 : }
    1057                 :             : 
    1058                 :             : /* Process an "include" directive, starting with the optional space
    1059                 :             :    after the "include".  Read in the file and use HANDLE_DIRECTIVE
    1060                 :             :    to process each unknown directive.  LINENO is the line number on
    1061                 :             :    which the "include" occurred.  */
    1062                 :             : 
    1063                 :             : void
    1064                 :           0 : md_reader::handle_include (file_location loc)
    1065                 :             : {
    1066                 :           0 :   const char *filename;
    1067                 :           0 :   const char *old_filename;
    1068                 :           0 :   int old_lineno, old_colno;
    1069                 :           0 :   char *pathname;
    1070                 :           0 :   FILE *input_file, *old_file;
    1071                 :             : 
    1072                 :           0 :   filename = read_string (false);
    1073                 :           0 :   input_file = NULL;
    1074                 :             : 
    1075                 :             :   /* If the specified file name is absolute, skip the include stack.  */
    1076                 :           0 :   if (!IS_ABSOLUTE_PATH (filename))
    1077                 :             :     {
    1078                 :           0 :       struct file_name_list *stackp;
    1079                 :             : 
    1080                 :             :       /* Search the directory path, trying to open the file.  */
    1081                 :           0 :       for (stackp = m_first_dir_md_include; stackp; stackp = stackp->next)
    1082                 :             :         {
    1083                 :           0 :           static const char sep[2] = { DIR_SEPARATOR, '\0' };
    1084                 :             : 
    1085                 :           0 :           pathname = concat (stackp->fname, sep, filename, NULL);
    1086                 :           0 :           input_file = fopen (pathname, "r");
    1087                 :           0 :           if (input_file != NULL)
    1088                 :             :             break;
    1089                 :           0 :           free (pathname);
    1090                 :             :         }
    1091                 :             :     }
    1092                 :             : 
    1093                 :             :   /* If we haven't managed to open the file yet, try combining the
    1094                 :             :      filename with BASE_DIR.  */
    1095                 :           0 :   if (input_file == NULL)
    1096                 :             :     {
    1097                 :           0 :       if (m_base_dir)
    1098                 :           0 :         pathname = concat (m_base_dir, filename, NULL);
    1099                 :             :       else
    1100                 :           0 :         pathname = xstrdup (filename);
    1101                 :           0 :       input_file = fopen (pathname, "r");
    1102                 :             :     }
    1103                 :             : 
    1104                 :           0 :   if (input_file == NULL)
    1105                 :             :     {
    1106                 :           0 :       free (pathname);
    1107                 :           0 :       error_at (loc, "include file `%s' not found", filename);
    1108                 :           0 :       return;
    1109                 :             :     }
    1110                 :             : 
    1111                 :             :   /* Save the old cursor.  Note that the LINENO argument to this
    1112                 :             :      function is the beginning of the include statement, while
    1113                 :             :      read_md_lineno has already been advanced.  */
    1114                 :           0 :   old_file = m_read_md_file;
    1115                 :           0 :   old_filename = m_read_md_filename;
    1116                 :           0 :   old_lineno = m_read_md_lineno;
    1117                 :           0 :   old_colno = m_read_md_colno;
    1118                 :             : 
    1119                 :           0 :   if (include_callback)
    1120                 :           0 :     include_callback (pathname);
    1121                 :             : 
    1122                 :           0 :   m_read_md_file = input_file;
    1123                 :           0 :   m_read_md_filename = pathname;
    1124                 :             : 
    1125                 :           0 :   handle_file ();
    1126                 :             : 
    1127                 :             :   /* Restore the old cursor.  */
    1128                 :           0 :   m_read_md_file = old_file;
    1129                 :           0 :   m_read_md_filename = old_filename;
    1130                 :           0 :   m_read_md_lineno = old_lineno;
    1131                 :           0 :   m_read_md_colno = old_colno;
    1132                 :             : 
    1133                 :             :   /* Do not free the pathname.  It is attached to the various rtx
    1134                 :             :      queue elements.  */
    1135                 :             : }
    1136                 :             : 
    1137                 :             : /* Process the current file, assuming that read_md_file and
    1138                 :             :    read_md_filename are valid.  Use HANDLE_DIRECTIVE to handle
    1139                 :             :    unknown directives.  */
    1140                 :             : 
    1141                 :             : void
    1142                 :          93 : md_reader::handle_file ()
    1143                 :             : {
    1144                 :          93 :   struct md_name directive;
    1145                 :          93 :   int c;
    1146                 :             : 
    1147                 :          93 :   m_read_md_lineno = 1;
    1148                 :          93 :   m_read_md_colno = 0;
    1149                 :         185 :   while ((c = read_skip_spaces ()) != EOF)
    1150                 :             :     {
    1151                 :          93 :       file_location loc = get_current_location ();
    1152                 :          93 :       if (c != '(')
    1153                 :           0 :         fatal_expected_char ('(', c);
    1154                 :             : 
    1155                 :          93 :       read_name (&directive);
    1156                 :          93 :       if (strcmp (directive.string, "define_constants") == 0)
    1157                 :           0 :         handle_constants ();
    1158                 :          93 :       else if (strcmp (directive.string, "define_enum") == 0)
    1159                 :           0 :         handle_enum (loc, true);
    1160                 :          93 :       else if (strcmp (directive.string, "define_c_enum") == 0)
    1161                 :           0 :         handle_enum (loc, false);
    1162                 :          93 :       else if (strcmp (directive.string, "include") == 0)
    1163                 :           0 :         handle_include (loc);
    1164                 :             :       else
    1165                 :          93 :         handle_unknown_directive (loc, directive.string);
    1166                 :             : 
    1167                 :          92 :       require_char_ws (')');
    1168                 :             :     }
    1169                 :          92 :   fclose (m_read_md_file);
    1170                 :          92 : }
    1171                 :             : 
    1172                 :             : /* Like handle_file, but for top-level files.  Set up m_toplevel_fname
    1173                 :             :    and m_base_dir accordingly.  */
    1174                 :             : 
    1175                 :             : void
    1176                 :          93 : md_reader::handle_toplevel_file ()
    1177                 :             : {
    1178                 :          93 :   const char *base;
    1179                 :             : 
    1180                 :          93 :   m_toplevel_fname = m_read_md_filename;
    1181                 :          93 :   base = lbasename (m_toplevel_fname);
    1182                 :          93 :   if (base == m_toplevel_fname)
    1183                 :           0 :     m_base_dir = NULL;
    1184                 :             :   else
    1185                 :          93 :     m_base_dir = xstrndup (m_toplevel_fname, base - m_toplevel_fname);
    1186                 :             : 
    1187                 :          93 :   handle_file ();
    1188                 :          92 : }
    1189                 :             : 
    1190                 :             : file_location
    1191                 :        8964 : md_reader::get_current_location () const
    1192                 :             : {
    1193                 :        8964 :   return file_location (m_read_md_filename, m_read_md_lineno, m_read_md_colno);
    1194                 :             : }
    1195                 :             : 
    1196                 :             : /* Parse a -I option with argument ARG.  */
    1197                 :             : 
    1198                 :             : void
    1199                 :           0 : md_reader::add_include_path (const char *arg)
    1200                 :             : {
    1201                 :           0 :   struct file_name_list *dirtmp;
    1202                 :             : 
    1203                 :           0 :   dirtmp = XNEW (struct file_name_list);
    1204                 :           0 :   dirtmp->next = 0;
    1205                 :           0 :   dirtmp->fname = arg;
    1206                 :           0 :   *m_last_dir_md_include_ptr = dirtmp;
    1207                 :           0 :   m_last_dir_md_include_ptr = &dirtmp->next;
    1208                 :           0 : }
    1209                 :             : 
    1210                 :             : #ifdef GENERATOR_FILE
    1211                 :             : 
    1212                 :             : /* The main routine for reading .md files.  Try to process all the .md
    1213                 :             :    files specified on the command line and return true if no error occurred.
    1214                 :             : 
    1215                 :             :    ARGC and ARGV are the arguments to main.
    1216                 :             : 
    1217                 :             :    PARSE_OPT, if nonnull, is passed all unknown command-line arguments.
    1218                 :             :    It should return true if it recognizes the argument or false if a
    1219                 :             :    generic error should be reported.  */
    1220                 :             : 
    1221                 :             : bool
    1222                 :             : md_reader::read_md_files (int argc, const char **argv,
    1223                 :             :                           bool (*parse_opt) (const char *))
    1224                 :             : {
    1225                 :             :   int i;
    1226                 :             :   bool no_more_options;
    1227                 :             :   bool already_read_stdin;
    1228                 :             :   int num_files;
    1229                 :             : 
    1230                 :             :   /* First we loop over all the options.  */
    1231                 :             :   for (i = 1; i < argc; i++)
    1232                 :             :     if (argv[i][0] == '-')
    1233                 :             :       {
    1234                 :             :         /* An argument consisting of exactly one dash is a request to
    1235                 :             :            read stdin.  This will be handled in the second loop.  */
    1236                 :             :         if (argv[i][1] == '\0')
    1237                 :             :           continue;
    1238                 :             : 
    1239                 :             :         /* An argument consisting of just two dashes causes option
    1240                 :             :            parsing to cease.  */
    1241                 :             :         if (argv[i][1] == '-' && argv[i][2] == '\0')
    1242                 :             :           break;
    1243                 :             : 
    1244                 :             :         if (argv[i][1] == 'I')
    1245                 :             :           {
    1246                 :             :             if (argv[i][2] != '\0')
    1247                 :             :               add_include_path (argv[i] + 2);
    1248                 :             :             else if (++i < argc)
    1249                 :             :               add_include_path (argv[i]);
    1250                 :             :             else
    1251                 :             :               fatal ("directory name missing after -I option");
    1252                 :             :             continue;
    1253                 :             :           }
    1254                 :             : 
    1255                 :             :         /* The program may have provided a callback so it can
    1256                 :             :            accept its own options.  */
    1257                 :             :         if (parse_opt && parse_opt (argv[i]))
    1258                 :             :           continue;
    1259                 :             : 
    1260                 :             :         fatal ("invalid option `%s'", argv[i]);
    1261                 :             :       }
    1262                 :             : 
    1263                 :             :   /* Now loop over all input files.  */
    1264                 :             :   num_files = 0;
    1265                 :             :   no_more_options = false;
    1266                 :             :   already_read_stdin = false;
    1267                 :             :   for (i = 1; i < argc; i++)
    1268                 :             :     {
    1269                 :             :       if (argv[i][0] == '-')
    1270                 :             :         {
    1271                 :             :           if (argv[i][1] == '\0')
    1272                 :             :             {
    1273                 :             :               /* Read stdin.  */
    1274                 :             :               if (already_read_stdin)
    1275                 :             :                 fatal ("cannot read standard input twice");
    1276                 :             : 
    1277                 :             :               m_read_md_file = stdin;
    1278                 :             :               m_read_md_filename = "<stdin>";
    1279                 :             :               handle_toplevel_file ();
    1280                 :             :               already_read_stdin = true;
    1281                 :             :               continue;
    1282                 :             :             }
    1283                 :             :           else if (argv[i][1] == '-' && argv[i][2] == '\0')
    1284                 :             :             {
    1285                 :             :               /* No further arguments are to be treated as options.  */
    1286                 :             :               no_more_options = true;
    1287                 :             :               continue;
    1288                 :             :             }
    1289                 :             :           else if (!no_more_options)
    1290                 :             :             continue;
    1291                 :             :         }
    1292                 :             : 
    1293                 :             :       /* If we get here we are looking at a non-option argument, i.e.
    1294                 :             :          a file to be processed.  */
    1295                 :             :       m_read_md_filename = argv[i];
    1296                 :             :       m_read_md_file = fopen (m_read_md_filename, "r");
    1297                 :             :       if (m_read_md_file == 0)
    1298                 :             :         {
    1299                 :             :           perror (m_read_md_filename);
    1300                 :             :           return false;
    1301                 :             :         }
    1302                 :             :       handle_toplevel_file ();
    1303                 :             :       num_files++;
    1304                 :             :     }
    1305                 :             : 
    1306                 :             :   /* If we get to this point without having seen any files to process,
    1307                 :             :      read the standard input now.  */
    1308                 :             :   if (num_files == 0 && !already_read_stdin)
    1309                 :             :     {
    1310                 :             :       m_read_md_file = stdin;
    1311                 :             :       m_read_md_filename = "<stdin>";
    1312                 :             :       handle_toplevel_file ();
    1313                 :             :     }
    1314                 :             : 
    1315                 :             :   return !have_error;
    1316                 :             : }
    1317                 :             : 
    1318                 :             : #endif /* #ifdef GENERATOR_FILE */
    1319                 :             : 
    1320                 :             : /* Read FILENAME.  */
    1321                 :             : 
    1322                 :             : bool
    1323                 :          76 : md_reader::read_file (const char *filename)
    1324                 :             : {
    1325                 :          76 :   m_read_md_filename = filename;
    1326                 :          76 :   m_read_md_file = fopen (m_read_md_filename, "r");
    1327                 :          76 :   if (m_read_md_file == 0)
    1328                 :             :     {
    1329                 :           0 :       perror (m_read_md_filename);
    1330                 :           0 :       return false;
    1331                 :             :     }
    1332                 :          76 :   handle_toplevel_file ();
    1333                 :          76 :   return !have_error;
    1334                 :             : }
    1335                 :             : 
    1336                 :             : /* Read FILENAME, filtering to just the given lines.  */
    1337                 :             : 
    1338                 :             : bool
    1339                 :          17 : md_reader::read_file_fragment (const char *filename,
    1340                 :             :                                int first_line,
    1341                 :             :                                int last_line)
    1342                 :             : {
    1343                 :          17 :   m_read_md_filename = filename;
    1344                 :          17 :   m_read_md_file = fopen (m_read_md_filename, "r");
    1345                 :          17 :   if (m_read_md_file == 0)
    1346                 :             :     {
    1347                 :           0 :       perror (m_read_md_filename);
    1348                 :           0 :       return false;
    1349                 :             :     }
    1350                 :          17 :   m_first_line = first_line;
    1351                 :          17 :   m_last_line = last_line;
    1352                 :          17 :   handle_toplevel_file ();
    1353                 :          16 :   return !have_error;
    1354                 :             : }
    1355                 :             : 
    1356                 :             : /* class noop_reader : public md_reader */
    1357                 :             : 
    1358                 :             : /* A dummy implementation which skips unknown directives.  */
    1359                 :             : void
    1360                 :           0 : noop_reader::handle_unknown_directive (file_location loc, const char *)
    1361                 :             : {
    1362                 :           0 :   read_skip_construct (1, loc);
    1363                 :           0 : }
        

Generated by: LCOV version 2.0-1

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.