LCOV - code coverage report
Current view: top level - gcc - read-md.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 220 551 39.9 %
Date: 2020-03-28 11:57:23 Functions: 23 54 42.6 %
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-2020 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.c 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                 :       6265 : leading_string_hash (const void *def)
      59                 :            : {
      60                 :       6265 :   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                 :         65 : leading_ptr_hash (const void *def)
      77                 :            : {
      78                 :         65 :   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                 :          1 : leading_ptr_eq_p (const void *def1, const void *def2)
      85                 :            : {
      86                 :          1 :   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                 :         65 : md_reader::set_md_ptr_loc (const void *ptr, file_location file_loc)
      93                 :            : {
      94                 :         65 :   struct ptr_loc *loc;
      95                 :            : 
      96                 :         65 :   loc = (struct ptr_loc *) obstack_alloc (&m_ptr_loc_obstack,
      97                 :            :                                           sizeof (struct ptr_loc));
      98                 :         65 :   loc->ptr = ptr;
      99                 :         65 :   loc->loc = file_loc;
     100                 :         65 :   *htab_find_slot (m_ptr_locs, loc, INSERT) = loc;
     101                 :         65 : }
     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)
     136                 :            : {
     137                 :          0 :   fprint_md_ptr_loc (stdout, 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                 :         42 :   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                 :            :           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                 :      15731 : read_skip_spaces (void)
     311                 :            : {
     312                 :      41016 :   int c;
     313                 :            : 
     314                 :      41016 :   while (1)
     315                 :            :     {
     316                 :      41016 :       c = read_char ();
     317                 :      41016 :       switch (c)
     318                 :            :         {
     319                 :            :         case ' ': case '\t': case '\f': case '\r': case '\n':
     320                 :            :           break;
     321                 :            : 
     322                 :       3356 :         case ';':
     323                 :       3356 :           do
     324                 :       3356 :             c = read_char ();
     325                 :       3356 :           while (c != '\n' && c != EOF);
     326                 :            :           break;
     327                 :            : 
     328                 :          2 :         case '/':
     329                 :          2 :           {
     330                 :          2 :             int prevc;
     331                 :          2 :             c = read_char ();
     332                 :          2 :             if (c != '*')
     333                 :            :               {
     334                 :          0 :                 unread_char (c);
     335                 :          0 :                 fatal_with_file_and_line ("stray '/' in file");
     336                 :            :               }
     337                 :            : 
     338                 :            :             prevc = 0;
     339                 :        290 :             while ((c = read_char ()) && c != EOF)
     340                 :            :               {
     341                 :        290 :                 if (prevc == '*' && c == '/')
     342                 :            :                   break;
     343                 :            :                 prevc = c;
     344                 :            :               }
     345                 :            :           }
     346                 :            :           break;
     347                 :            : 
     348                 :      15731 :         default:
     349                 :      15731 :           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                 :        442 : md_reader::require_char (char expected)
     359                 :            : {
     360                 :        442 :   int ch = read_char ();
     361                 :        442 :   if (ch != expected)
     362                 :          0 :     fatal_expected_char (expected, ch);
     363                 :        442 : }
     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                 :       4042 : md_reader::require_char_ws (char expected)
     370                 :            : {
     371                 :       4042 :   int ch = read_skip_spaces ();
     372                 :       4042 :   if (ch != expected)
     373                 :          0 :     fatal_expected_char (expected, ch);
     374                 :       4042 : }
     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                 :        201 : md_reader::require_word_ws (const char *expected)
     381                 :            : {
     382                 :        201 :   struct md_name name;
     383                 :        201 :   read_name (&name);
     384                 :        201 :   if (strcmp (name.string, expected))
     385                 :          0 :     fatal_with_file_and_line ("missing '%s'", expected);
     386                 :        201 : }
     387                 :            : 
     388                 :            : /* Read the next character from the file.  */
     389                 :            : 
     390                 :            : int
     391                 :      81118 : md_reader::read_char (void)
     392                 :            : {
     393                 :      81118 :   int ch;
     394                 :            : 
     395                 :      81118 :   ch = getc (m_read_md_file);
     396                 :      81118 :   if (ch == '\n')
     397                 :            :     {
     398                 :       2287 :       m_read_md_lineno++;
     399                 :       2287 :       m_last_line_colno = m_read_md_colno;
     400                 :       2287 :       m_read_md_colno = 0;
     401                 :            :     }
     402                 :            :   else
     403                 :      78831 :     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                 :      81118 :   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                 :       9302 : md_reader::unread_char (int ch)
     422                 :            : {
     423                 :       9302 :   if (ch == '\n')
     424                 :            :     {
     425                 :        374 :       m_read_md_lineno--;
     426                 :        374 :       m_read_md_colno = m_last_line_colno;
     427                 :            :     }
     428                 :            :   else
     429                 :       8928 :     m_read_md_colno--;
     430                 :       9302 :   ungetc (ch, m_read_md_file);
     431                 :       9302 : }
     432                 :            : 
     433                 :            : /* Peek at the next character from the file without consuming it.  */
     434                 :            : 
     435                 :            : int
     436                 :       1762 : md_reader::peek_char (void)
     437                 :            : {
     438                 :       1762 :   int ch = read_char ();
     439                 :       1762 :   unread_char (ch);
     440                 :       1762 :   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                 :       5392 : md_reader::read_name_1 (struct md_name *name, file_location *out_loc)
     448                 :            : {
     449                 :       5392 :   int c;
     450                 :       5392 :   size_t i;
     451                 :       5392 :   int angle_bracket_depth;
     452                 :            : 
     453                 :       5392 :   c = read_skip_spaces ();
     454                 :            : 
     455                 :       5392 :   *out_loc = get_current_location ();
     456                 :            : 
     457                 :       5392 :   i = 0;
     458                 :       5392 :   angle_bracket_depth = 0;
     459                 :      47446 :   while (1)
     460                 :            :     {
     461                 :      26419 :       if (c == '<')
     462                 :        182 :         angle_bracket_depth++;
     463                 :            : 
     464                 :      26419 :       if ((c == '>') && (angle_bracket_depth > 0))
     465                 :        182 :           angle_bracket_depth--;
     466                 :            : 
     467                 :      26419 :       if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r'
     468                 :      22962 :           || c == EOF)
     469                 :            :         break;
     470                 :      22962 :       if (angle_bracket_depth == 0)
     471                 :            :         {
     472                 :      22576 :           if (c == ':' || c == ')' || c == ']'
     473                 :      21139 :               || c == '"' || c == '/' || c == '(' || c == '[')
     474                 :            :             {
     475                 :       1935 :               unread_char (c);
     476                 :       1935 :               break;
     477                 :            :             }
     478                 :            :         }
     479                 :            : 
     480                 :      21027 :       if (i == sizeof (name->buffer) - 1)
     481                 :          0 :         fatal_with_file_and_line ("name too long");
     482                 :      21027 :       name->buffer[i++] = c;
     483                 :            : 
     484                 :      21027 :       c = read_char ();
     485                 :            :     }
     486                 :            : 
     487                 :       5392 :   if (i == 0)
     488                 :            :     return false;
     489                 :            : 
     490                 :       5392 :   name->buffer[i] = 0;
     491                 :       5392 :   name->string = name->buffer;
     492                 :            : 
     493                 :       5392 :   if (m_md_constants)
     494                 :            :     {
     495                 :            :       /* Do constant expansion.  */
     496                 :       5392 :       struct md_constant *def;
     497                 :            : 
     498                 :       5392 :       do
     499                 :            :         {
     500                 :       5392 :           struct md_constant tmp_def;
     501                 :            : 
     502                 :       5392 :           tmp_def.name = name->string;
     503                 :       5392 :           def = (struct md_constant *) htab_find (m_md_constants, &tmp_def);
     504                 :       5392 :           if (def)
     505                 :          0 :             name->string = def->value;
     506                 :            :         }
     507                 :       5392 :       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                 :       5392 : md_reader::read_name (struct md_name *name)
     518                 :            : {
     519                 :       5392 :   file_location loc;
     520                 :       5392 :   if (!read_name_1 (name, &loc))
     521                 :          0 :     fatal_with_file_and_line ("missing name or number");
     522                 :       5392 :   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                 :        420 : md_reader::read_quoted_string ()
     599                 :            : {
     600                 :       9240 :   int c;
     601                 :            : 
     602                 :       9240 :   while (1)
     603                 :            :     {
     604                 :       9240 :       c = read_char (); /* Read the string  */
     605                 :       9240 :       if (c == '\\')
     606                 :            :         {
     607                 :          0 :           read_escape ();
     608                 :          0 :           continue;
     609                 :            :         }
     610                 :       9240 :       else if (c == '"' || c == EOF)
     611                 :            :         break;
     612                 :            : 
     613                 :       8820 :       obstack_1grow (&m_string_obstack, c);
     614                 :            :     }
     615                 :            : 
     616                 :        420 :   obstack_1grow (&m_string_obstack, 0);
     617                 :        420 :   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                 :         69 : md_reader::read_string (int star_if_braced)
     663                 :            : {
     664                 :         69 :   char *stringbuf;
     665                 :         69 :   int saw_paren = 0;
     666                 :         69 :   int c;
     667                 :            : 
     668                 :         69 :   c = read_skip_spaces ();
     669                 :         69 :   if (c == '(')
     670                 :            :     {
     671                 :         14 :       saw_paren = 1;
     672                 :         14 :       c = read_skip_spaces ();
     673                 :            :     }
     674                 :            : 
     675                 :         69 :   file_location loc = get_current_location ();
     676                 :         69 :   if (c == '"')
     677                 :         65 :     stringbuf = read_quoted_string ();
     678                 :          4 :   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                 :          4 :   else if (saw_paren && c == 'n')
     685                 :            :     {
     686                 :            :       /* Handle (nil) by returning NULL.  */
     687                 :          4 :       require_char ('i');
     688                 :          4 :       require_char ('l');
     689                 :          4 :       require_char_ws (')');
     690                 :          4 :       return NULL;
     691                 :            :     }
     692                 :            :   else
     693                 :          0 :     fatal_with_file_and_line ("expected `\"' or `{', found `%c'", c);
     694                 :            : 
     695                 :         65 :   if (saw_paren)
     696                 :         10 :     require_char_ws (')');
     697                 :            : 
     698                 :         65 :   set_md_ptr_loc (stringbuf, loc);
     699                 :         65 :   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                 :          0 :   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 :   struct md_name name;
     906                 :          0 :   struct enum_type *def;
     907                 :          0 :   struct enum_value *ev;
     908                 :          0 :   void **slot;
     909                 :          0 :   int c;
     910                 :            : 
     911                 :          0 :   enum_name = read_string (false);
     912                 :          0 :   slot = htab_find_slot (m_enum_types, &enum_name, INSERT);
     913                 :          0 :   if (*slot)
     914                 :            :     {
     915                 :          0 :       def = (struct enum_type *) *slot;
     916                 :          0 :       if (def->md_p != md_p)
     917                 :          0 :         error_at (loc, "redefining `%s' as a different type of enum",
     918                 :            :                   enum_name);
     919                 :            :     }
     920                 :            :   else
     921                 :            :     {
     922                 :          0 :       def = XNEW (struct enum_type);
     923                 :          0 :       def->name = enum_name;
     924                 :          0 :       def->md_p = md_p;
     925                 :          0 :       def->values = 0;
     926                 :          0 :       def->tail_ptr = &def->values;
     927                 :          0 :       def->num_values = 0;
     928                 :          0 :       *slot = def;
     929                 :            :     }
     930                 :            : 
     931                 :          0 :   require_char_ws ('[');
     932                 :            : 
     933                 :          0 :   while ((c = read_skip_spaces ()) != ']')
     934                 :            :     {
     935                 :          0 :       if (c == EOF)
     936                 :            :         {
     937                 :          0 :           error_at (loc, "unterminated construct");
     938                 :          0 :           exit (1);
     939                 :            :         }
     940                 :          0 :       unread_char (c);
     941                 :          0 :       read_name (&name);
     942                 :            : 
     943                 :          0 :       ev = XNEW (struct enum_value);
     944                 :          0 :       ev->next = 0;
     945                 :          0 :       if (md_p)
     946                 :            :         {
     947                 :          0 :           value_name = concat (def->name, "_", name.string, NULL);
     948                 :          0 :           upcase_string (value_name);
     949                 :          0 :           ev->name = xstrdup (name.string);
     950                 :            :         }
     951                 :            :       else
     952                 :            :         {
     953                 :          0 :           value_name = xstrdup (name.string);
     954                 :          0 :           ev->name = value_name;
     955                 :            :         }
     956                 :          0 :       ev->def = add_constant (get_md_constants (), value_name,
     957                 :          0 :                               md_decimal_string (def->num_values), def);
     958                 :            : 
     959                 :          0 :       *def->tail_ptr = ev;
     960                 :          0 :       def->tail_ptr = &ev->next;
     961                 :          0 :       def->num_values++;
     962                 :            :     }
     963                 :          0 : }
     964                 :            : 
     965                 :            : /* Try to find the definition of the given enum.  Return null on failure.  */
     966                 :            : 
     967                 :            : struct enum_type *
     968                 :          0 : md_reader::lookup_enum_type (const char *name)
     969                 :            : {
     970                 :          0 :   return (struct enum_type *) htab_find (m_enum_types, &name);
     971                 :            : }
     972                 :            : 
     973                 :            : /* For every enum definition, call CALLBACK with two arguments:
     974                 :            :    a pointer to the constant definition and INFO.  Stop when CALLBACK
     975                 :            :    returns zero.  */
     976                 :            : 
     977                 :            : void
     978                 :          0 : md_reader::traverse_enum_types (htab_trav callback, void *info)
     979                 :            : {
     980                 :          0 :   htab_traverse (m_enum_types, callback, info);
     981                 :          0 : }
     982                 :            : 
     983                 :            : 
     984                 :            : /* Constructor for md_reader.  */
     985                 :            : 
     986                 :         55 : md_reader::md_reader (bool compact)
     987                 :            : : m_compact (compact),
     988                 :            :   m_toplevel_fname (NULL),
     989                 :            :   m_base_dir (NULL),
     990                 :            :   m_read_md_file (NULL),
     991                 :            :   m_read_md_filename (NULL),
     992                 :            :   m_read_md_lineno (0),
     993                 :            :   m_read_md_colno (0),
     994                 :            :   m_first_dir_md_include (NULL),
     995                 :         55 :   m_last_dir_md_include_ptr (&m_first_dir_md_include),
     996                 :            :   m_first_line (0),
     997                 :            :   m_last_line (0),
     998                 :            :   m_first_overload (NULL),
     999                 :         55 :   m_next_overload_ptr (&m_first_overload),
    1000                 :         55 :   m_overloads_htab (NULL)
    1001                 :            : {
    1002                 :            :   /* Set the global singleton pointer.  */
    1003                 :         55 :   md_reader_ptr = this;
    1004                 :            : 
    1005                 :         55 :   obstack_init (&m_string_obstack);
    1006                 :            : 
    1007                 :         55 :   m_ptr_locs = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
    1008                 :         55 :   obstack_init (&m_ptr_loc_obstack);
    1009                 :            : 
    1010                 :         55 :   m_joined_conditions = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
    1011                 :         55 :   obstack_init (&m_joined_conditions_obstack);
    1012                 :            : 
    1013                 :         55 :   m_md_constants = htab_create (31, leading_string_hash,
    1014                 :            :                                 leading_string_eq_p, (htab_del) 0);
    1015                 :            : 
    1016                 :         55 :   m_enum_types = htab_create (31, leading_string_hash,
    1017                 :            :                               leading_string_eq_p, (htab_del) 0);
    1018                 :            : 
    1019                 :            :   /* Unlock the stdio streams.  */
    1020                 :         55 :   unlock_std_streams ();
    1021                 :         55 : }
    1022                 :            : 
    1023                 :            : /* md_reader's destructor.  */
    1024                 :            : 
    1025                 :        108 : md_reader::~md_reader ()
    1026                 :            : {
    1027                 :         54 :   free (m_base_dir);
    1028                 :            : 
    1029                 :         54 :   htab_delete (m_enum_types);
    1030                 :            : 
    1031                 :         54 :   htab_delete (m_md_constants);
    1032                 :            : 
    1033                 :         54 :   obstack_free (&m_joined_conditions_obstack, NULL);
    1034                 :         54 :   htab_delete (m_joined_conditions);
    1035                 :            : 
    1036                 :         54 :   obstack_free (&m_ptr_loc_obstack, NULL);
    1037                 :         54 :   htab_delete (m_ptr_locs);
    1038                 :            : 
    1039                 :         54 :   obstack_free (&m_string_obstack, NULL);
    1040                 :            : 
    1041                 :            :   /* Clear the global singleton pointer.  */
    1042                 :         54 :   md_reader_ptr = NULL;
    1043                 :         54 : }
    1044                 :            : 
    1045                 :            : /* Process an "include" directive, starting with the optional space
    1046                 :            :    after the "include".  Read in the file and use HANDLE_DIRECTIVE
    1047                 :            :    to process each unknown directive.  LINENO is the line number on
    1048                 :            :    which the "include" occurred.  */
    1049                 :            : 
    1050                 :            : void
    1051                 :          0 : md_reader::handle_include (file_location loc)
    1052                 :            : {
    1053                 :          0 :   const char *filename;
    1054                 :          0 :   const char *old_filename;
    1055                 :          0 :   int old_lineno, old_colno;
    1056                 :          0 :   char *pathname;
    1057                 :          0 :   FILE *input_file, *old_file;
    1058                 :            : 
    1059                 :          0 :   filename = read_string (false);
    1060                 :          0 :   input_file = NULL;
    1061                 :            : 
    1062                 :            :   /* If the specified file name is absolute, skip the include stack.  */
    1063                 :          0 :   if (!IS_ABSOLUTE_PATH (filename))
    1064                 :            :     {
    1065                 :          0 :       struct file_name_list *stackp;
    1066                 :            : 
    1067                 :            :       /* Search the directory path, trying to open the file.  */
    1068                 :          0 :       for (stackp = m_first_dir_md_include; stackp; stackp = stackp->next)
    1069                 :            :         {
    1070                 :          0 :           static const char sep[2] = { DIR_SEPARATOR, '\0' };
    1071                 :            : 
    1072                 :          0 :           pathname = concat (stackp->fname, sep, filename, NULL);
    1073                 :          0 :           input_file = fopen (pathname, "r");
    1074                 :          0 :           if (input_file != NULL)
    1075                 :            :             break;
    1076                 :          0 :           free (pathname);
    1077                 :            :         }
    1078                 :            :     }
    1079                 :            : 
    1080                 :            :   /* If we haven't managed to open the file yet, try combining the
    1081                 :            :      filename with BASE_DIR.  */
    1082                 :          0 :   if (input_file == NULL)
    1083                 :            :     {
    1084                 :          0 :       if (m_base_dir)
    1085                 :          0 :         pathname = concat (m_base_dir, filename, NULL);
    1086                 :            :       else
    1087                 :          0 :         pathname = xstrdup (filename);
    1088                 :          0 :       input_file = fopen (pathname, "r");
    1089                 :            :     }
    1090                 :            : 
    1091                 :          0 :   if (input_file == NULL)
    1092                 :            :     {
    1093                 :          0 :       free (pathname);
    1094                 :          0 :       error_at (loc, "include file `%s' not found", filename);
    1095                 :          0 :       return;
    1096                 :            :     }
    1097                 :            : 
    1098                 :            :   /* Save the old cursor.  Note that the LINENO argument to this
    1099                 :            :      function is the beginning of the include statement, while
    1100                 :            :      read_md_lineno has already been advanced.  */
    1101                 :          0 :   old_file = m_read_md_file;
    1102                 :          0 :   old_filename = m_read_md_filename;
    1103                 :          0 :   old_lineno = m_read_md_lineno;
    1104                 :          0 :   old_colno = m_read_md_colno;
    1105                 :            : 
    1106                 :          0 :   if (include_callback)
    1107                 :          0 :     include_callback (pathname);
    1108                 :            : 
    1109                 :          0 :   m_read_md_file = input_file;
    1110                 :          0 :   m_read_md_filename = pathname;
    1111                 :            : 
    1112                 :          0 :   handle_file ();
    1113                 :            : 
    1114                 :            :   /* Restore the old cursor.  */
    1115                 :          0 :   m_read_md_file = old_file;
    1116                 :          0 :   m_read_md_filename = old_filename;
    1117                 :          0 :   m_read_md_lineno = old_lineno;
    1118                 :          0 :   m_read_md_colno = old_colno;
    1119                 :            : 
    1120                 :            :   /* Do not free the pathname.  It is attached to the various rtx
    1121                 :            :      queue elements.  */
    1122                 :            : }
    1123                 :            : 
    1124                 :            : /* Process the current file, assuming that read_md_file and
    1125                 :            :    read_md_filename are valid.  Use HANDLE_DIRECTIVE to handle
    1126                 :            :    unknown directives.  */
    1127                 :            : 
    1128                 :            : void
    1129                 :         55 : md_reader::handle_file ()
    1130                 :            : {
    1131                 :         55 :   struct md_name directive;
    1132                 :         55 :   int c;
    1133                 :            : 
    1134                 :         55 :   m_read_md_lineno = 1;
    1135                 :         55 :   m_read_md_colno = 0;
    1136                 :        109 :   while ((c = read_skip_spaces ()) != EOF)
    1137                 :            :     {
    1138                 :         55 :       file_location loc = get_current_location ();
    1139                 :         55 :       if (c != '(')
    1140                 :          0 :         fatal_expected_char ('(', c);
    1141                 :            : 
    1142                 :         55 :       read_name (&directive);
    1143                 :         55 :       if (strcmp (directive.string, "define_constants") == 0)
    1144                 :          0 :         handle_constants ();
    1145                 :         55 :       else if (strcmp (directive.string, "define_enum") == 0)
    1146                 :          0 :         handle_enum (loc, true);
    1147                 :         55 :       else if (strcmp (directive.string, "define_c_enum") == 0)
    1148                 :          0 :         handle_enum (loc, false);
    1149                 :         55 :       else if (strcmp (directive.string, "include") == 0)
    1150                 :          0 :         handle_include (loc);
    1151                 :            :       else
    1152                 :         55 :         handle_unknown_directive (loc, directive.string);
    1153                 :            : 
    1154                 :         54 :       require_char_ws (')');
    1155                 :            :     }
    1156                 :         54 :   fclose (m_read_md_file);
    1157                 :         54 : }
    1158                 :            : 
    1159                 :            : /* Like handle_file, but for top-level files.  Set up m_toplevel_fname
    1160                 :            :    and m_base_dir accordingly.  */
    1161                 :            : 
    1162                 :            : void
    1163                 :         55 : md_reader::handle_toplevel_file ()
    1164                 :            : {
    1165                 :         55 :   const char *base;
    1166                 :            : 
    1167                 :         55 :   m_toplevel_fname = m_read_md_filename;
    1168                 :         55 :   base = lbasename (m_toplevel_fname);
    1169                 :         55 :   if (base == m_toplevel_fname)
    1170                 :          0 :     m_base_dir = NULL;
    1171                 :            :   else
    1172                 :         55 :     m_base_dir = xstrndup (m_toplevel_fname, base - m_toplevel_fname);
    1173                 :            : 
    1174                 :         55 :   handle_file ();
    1175                 :         54 : }
    1176                 :            : 
    1177                 :            : file_location
    1178                 :       7032 : md_reader::get_current_location () const
    1179                 :            : {
    1180                 :       7032 :   return file_location (m_read_md_filename, m_read_md_lineno, m_read_md_colno);
    1181                 :            : }
    1182                 :            : 
    1183                 :            : /* Parse a -I option with argument ARG.  */
    1184                 :            : 
    1185                 :            : void
    1186                 :          0 : md_reader::add_include_path (const char *arg)
    1187                 :            : {
    1188                 :          0 :   struct file_name_list *dirtmp;
    1189                 :            : 
    1190                 :          0 :   dirtmp = XNEW (struct file_name_list);
    1191                 :          0 :   dirtmp->next = 0;
    1192                 :          0 :   dirtmp->fname = arg;
    1193                 :          0 :   *m_last_dir_md_include_ptr = dirtmp;
    1194                 :          0 :   m_last_dir_md_include_ptr = &dirtmp->next;
    1195                 :          0 : }
    1196                 :            : 
    1197                 :            : #ifdef GENERATOR_FILE
    1198                 :            : 
    1199                 :            : /* The main routine for reading .md files.  Try to process all the .md
    1200                 :            :    files specified on the command line and return true if no error occurred.
    1201                 :            : 
    1202                 :            :    ARGC and ARGV are the arguments to main.
    1203                 :            : 
    1204                 :            :    PARSE_OPT, if nonnull, is passed all unknown command-line arguments.
    1205                 :            :    It should return true if it recognizes the argument or false if a
    1206                 :            :    generic error should be reported.  */
    1207                 :            : 
    1208                 :            : bool
    1209                 :            : md_reader::read_md_files (int argc, const char **argv,
    1210                 :            :                           bool (*parse_opt) (const char *))
    1211                 :            : {
    1212                 :            :   int i;
    1213                 :            :   bool no_more_options;
    1214                 :            :   bool already_read_stdin;
    1215                 :            :   int num_files;
    1216                 :            : 
    1217                 :            :   /* First we loop over all the options.  */
    1218                 :            :   for (i = 1; i < argc; i++)
    1219                 :            :     if (argv[i][0] == '-')
    1220                 :            :       {
    1221                 :            :         /* An argument consisting of exactly one dash is a request to
    1222                 :            :            read stdin.  This will be handled in the second loop.  */
    1223                 :            :         if (argv[i][1] == '\0')
    1224                 :            :           continue;
    1225                 :            : 
    1226                 :            :         /* An argument consisting of just two dashes causes option
    1227                 :            :            parsing to cease.  */
    1228                 :            :         if (argv[i][1] == '-' && argv[i][2] == '\0')
    1229                 :            :           break;
    1230                 :            : 
    1231                 :            :         if (argv[i][1] == 'I')
    1232                 :            :           {
    1233                 :            :             if (argv[i][2] != '\0')
    1234                 :            :               add_include_path (argv[i] + 2);
    1235                 :            :             else if (++i < argc)
    1236                 :            :               add_include_path (argv[i]);
    1237                 :            :             else
    1238                 :            :               fatal ("directory name missing after -I option");
    1239                 :            :             continue;
    1240                 :            :           }
    1241                 :            : 
    1242                 :            :         /* The program may have provided a callback so it can
    1243                 :            :            accept its own options.  */
    1244                 :            :         if (parse_opt && parse_opt (argv[i]))
    1245                 :            :           continue;
    1246                 :            : 
    1247                 :            :         fatal ("invalid option `%s'", argv[i]);
    1248                 :            :       }
    1249                 :            : 
    1250                 :            :   /* Now loop over all input files.  */
    1251                 :            :   num_files = 0;
    1252                 :            :   no_more_options = false;
    1253                 :            :   already_read_stdin = false;
    1254                 :            :   for (i = 1; i < argc; i++)
    1255                 :            :     {
    1256                 :            :       if (argv[i][0] == '-')
    1257                 :            :         {
    1258                 :            :           if (argv[i][1] == '\0')
    1259                 :            :             {
    1260                 :            :               /* Read stdin.  */
    1261                 :            :               if (already_read_stdin)
    1262                 :            :                 fatal ("cannot read standard input twice");
    1263                 :            : 
    1264                 :            :               m_read_md_file = stdin;
    1265                 :            :               m_read_md_filename = "<stdin>";
    1266                 :            :               handle_toplevel_file ();
    1267                 :            :               already_read_stdin = true;
    1268                 :            :               continue;
    1269                 :            :             }
    1270                 :            :           else if (argv[i][1] == '-' && argv[i][2] == '\0')
    1271                 :            :             {
    1272                 :            :               /* No further arguments are to be treated as options.  */
    1273                 :            :               no_more_options = true;
    1274                 :            :               continue;
    1275                 :            :             }
    1276                 :            :           else if (!no_more_options)
    1277                 :            :             continue;
    1278                 :            :         }
    1279                 :            : 
    1280                 :            :       /* If we get here we are looking at a non-option argument, i.e.
    1281                 :            :          a file to be processed.  */
    1282                 :            :       m_read_md_filename = argv[i];
    1283                 :            :       m_read_md_file = fopen (m_read_md_filename, "r");
    1284                 :            :       if (m_read_md_file == 0)
    1285                 :            :         {
    1286                 :            :           perror (m_read_md_filename);
    1287                 :            :           return false;
    1288                 :            :         }
    1289                 :            :       handle_toplevel_file ();
    1290                 :            :       num_files++;
    1291                 :            :     }
    1292                 :            : 
    1293                 :            :   /* If we get to this point without having seen any files to process,
    1294                 :            :      read the standard input now.  */
    1295                 :            :   if (num_files == 0 && !already_read_stdin)
    1296                 :            :     {
    1297                 :            :       m_read_md_file = stdin;
    1298                 :            :       m_read_md_filename = "<stdin>";
    1299                 :            :       handle_toplevel_file ();
    1300                 :            :     }
    1301                 :            : 
    1302                 :            :   return !have_error;
    1303                 :            : }
    1304                 :            : 
    1305                 :            : #endif /* #ifdef GENERATOR_FILE */
    1306                 :            : 
    1307                 :            : /* Read FILENAME.  */
    1308                 :            : 
    1309                 :            : bool
    1310                 :         38 : md_reader::read_file (const char *filename)
    1311                 :            : {
    1312                 :         38 :   m_read_md_filename = filename;
    1313                 :         38 :   m_read_md_file = fopen (m_read_md_filename, "r");
    1314                 :         38 :   if (m_read_md_file == 0)
    1315                 :            :     {
    1316                 :          0 :       perror (m_read_md_filename);
    1317                 :          0 :       return false;
    1318                 :            :     }
    1319                 :         38 :   handle_toplevel_file ();
    1320                 :         38 :   return !have_error;
    1321                 :            : }
    1322                 :            : 
    1323                 :            : /* Read FILENAME, filtering to just the given lines.  */
    1324                 :            : 
    1325                 :            : bool
    1326                 :         17 : md_reader::read_file_fragment (const char *filename,
    1327                 :            :                                int first_line,
    1328                 :            :                                int last_line)
    1329                 :            : {
    1330                 :         17 :   m_read_md_filename = filename;
    1331                 :         17 :   m_read_md_file = fopen (m_read_md_filename, "r");
    1332                 :         17 :   if (m_read_md_file == 0)
    1333                 :            :     {
    1334                 :          0 :       perror (m_read_md_filename);
    1335                 :          0 :       return false;
    1336                 :            :     }
    1337                 :         17 :   m_first_line = first_line;
    1338                 :         17 :   m_last_line = last_line;
    1339                 :         17 :   handle_toplevel_file ();
    1340                 :         16 :   return !have_error;
    1341                 :            : }
    1342                 :            : 
    1343                 :            : /* class noop_reader : public md_reader */
    1344                 :            : 
    1345                 :            : /* A dummy implementation which skips unknown directives.  */
    1346                 :            : void
    1347                 :          0 : noop_reader::handle_unknown_directive (file_location loc, const char *)
    1348                 :            : {
    1349                 :          0 :   read_skip_construct (1, loc);
    1350                 :          0 : }

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.