Home | History | Annotate | Line # | Download | only in gas
input-file.c revision 1.5
      1  1.1  christos /* input_file.c - Deal with Input Files -
      2  1.5  christos    Copyright (C) 1987-2016 Free Software Foundation, Inc.
      3  1.1  christos 
      4  1.1  christos    This file is part of GAS, the GNU Assembler.
      5  1.1  christos 
      6  1.1  christos    GAS is free software; you can redistribute it and/or modify
      7  1.1  christos    it under the terms of the GNU General Public License as published by
      8  1.1  christos    the Free Software Foundation; either version 3, or (at your option)
      9  1.1  christos    any later version.
     10  1.1  christos 
     11  1.1  christos    GAS is distributed in the hope that it will be useful,
     12  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  1.1  christos    GNU General Public License for more details.
     15  1.1  christos 
     16  1.1  christos    You should have received a copy of the GNU General Public License
     17  1.1  christos    along with GAS; see the file COPYING.  If not, write to the Free
     18  1.1  christos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     19  1.1  christos    02110-1301, USA.  */
     20  1.1  christos 
     21  1.1  christos /* Confines all details of reading source bytes to this module.
     22  1.1  christos    All O/S specific crocks should live here.
     23  1.1  christos    What we lose in "efficiency" we gain in modularity.
     24  1.1  christos    Note we don't need to #include the "as.h" file. No common coupling!  */
     25  1.1  christos 
     26  1.1  christos #include "as.h"
     27  1.1  christos #include "input-file.h"
     28  1.1  christos #include "safe-ctype.h"
     29  1.1  christos 
     30  1.1  christos /* This variable is non-zero if the file currently being read should be
     31  1.1  christos    preprocessed by app.  It is zero if the file can be read straight in.  */
     32  1.1  christos int preprocess = 0;
     33  1.1  christos 
     34  1.1  christos /* This code opens a file, then delivers BUFFER_SIZE character
     35  1.1  christos    chunks of the file on demand.
     36  1.1  christos    BUFFER_SIZE is supposed to be a number chosen for speed.
     37  1.1  christos    The caller only asks once what BUFFER_SIZE is, and asks before
     38  1.1  christos    the nature of the input files (if any) is known.  */
     39  1.1  christos 
     40  1.1  christos #define BUFFER_SIZE (32 * 1024)
     41  1.1  christos 
     42  1.1  christos /* We use static data: the data area is not sharable.  */
     43  1.1  christos 
     44  1.1  christos static FILE *f_in;
     45  1.5  christos static const char *file_name;
     46  1.1  christos 
     47  1.1  christos /* Struct for saving the state of this module for file includes.  */
     48  1.1  christos struct saved_file
     49  1.1  christos   {
     50  1.1  christos     FILE * f_in;
     51  1.5  christos     const char * file_name;
     52  1.1  christos     int    preprocess;
     53  1.1  christos     char * app_save;
     54  1.1  christos   };
     55  1.1  christos 
     56  1.1  christos /* These hooks accommodate most operating systems.  */
     58  1.1  christos 
     59  1.1  christos void
     60  1.1  christos input_file_begin (void)
     61  1.1  christos {
     62  1.1  christos   f_in = (FILE *) 0;
     63  1.1  christos }
     64  1.1  christos 
     65  1.1  christos void
     66  1.1  christos input_file_end (void)
     67  1.1  christos {
     68  1.1  christos }
     69  1.1  christos 
     70  1.1  christos /* Return BUFFER_SIZE.  */
     71  1.1  christos size_t
     72  1.1  christos input_file_buffer_size (void)
     73  1.1  christos {
     74  1.1  christos   return (BUFFER_SIZE);
     75  1.1  christos }
     76  1.1  christos 
     77  1.1  christos /* Push the state of our input, returning a pointer to saved info that
     78  1.1  christos    can be restored with input_file_pop ().  */
     79  1.1  christos 
     80  1.1  christos char *
     81  1.1  christos input_file_push (void)
     82  1.3  christos {
     83  1.1  christos   struct saved_file *saved;
     84  1.5  christos 
     85  1.1  christos   saved = XNEW (struct saved_file);
     86  1.1  christos 
     87  1.1  christos   saved->f_in = f_in;
     88  1.1  christos   saved->file_name = file_name;
     89  1.1  christos   saved->preprocess = preprocess;
     90  1.1  christos   if (preprocess)
     91  1.1  christos     saved->app_save = app_push ();
     92  1.1  christos 
     93  1.1  christos   /* Initialize for new file.  */
     94  1.1  christos   input_file_begin ();
     95  1.1  christos 
     96  1.1  christos   return (char *) saved;
     97  1.1  christos }
     98  1.1  christos 
     99  1.1  christos void
    100  1.1  christos input_file_pop (char *arg)
    101  1.3  christos {
    102  1.1  christos   struct saved_file *saved = (struct saved_file *) arg;
    103  1.1  christos 
    104  1.1  christos   input_file_end ();		/* Close out old file.  */
    105  1.1  christos 
    106  1.1  christos   f_in = saved->f_in;
    107  1.1  christos   file_name = saved->file_name;
    108  1.1  christos   preprocess = saved->preprocess;
    109  1.1  christos   if (preprocess)
    110  1.1  christos     app_pop (saved->app_save);
    111  1.1  christos 
    112  1.1  christos   free (arg);
    113  1.1  christos }
    114  1.5  christos 
    115  1.5  christos /* Open the specified file, "" means stdin.  Filename must not be null.  */
    117  1.5  christos 
    118  1.1  christos void
    119  1.1  christos input_file_open (const char *filename,
    120  1.1  christos 		 int pre)
    121  1.1  christos {
    122  1.1  christos   int c;
    123  1.1  christos   char buf[80];
    124  1.1  christos 
    125  1.1  christos   preprocess = pre;
    126  1.1  christos 
    127  1.1  christos   gas_assert (filename != 0);	/* Filename may not be NULL.  */
    128  1.1  christos   if (filename[0])
    129  1.1  christos     {
    130  1.1  christos       f_in = fopen (filename, FOPEN_RT);
    131  1.1  christos       file_name = filename;
    132  1.1  christos     }
    133  1.1  christos   else
    134  1.1  christos     {
    135  1.1  christos       /* Use stdin for the input file.  */
    136  1.1  christos       f_in = stdin;
    137  1.1  christos       /* For error messages.  */
    138  1.1  christos       file_name = _("{standard input}");
    139  1.1  christos     }
    140  1.1  christos 
    141  1.1  christos   if (f_in == NULL)
    142  1.1  christos     {
    143  1.1  christos       as_bad (_("can't open %s for reading: %s"),
    144  1.1  christos 	      file_name, xstrerror (errno));
    145  1.1  christos       return;
    146  1.1  christos     }
    147  1.1  christos 
    148  1.1  christos   c = getc (f_in);
    149  1.1  christos 
    150  1.1  christos   if (ferror (f_in))
    151  1.1  christos     {
    152  1.1  christos       as_bad (_("can't read from %s: %s"),
    153  1.1  christos 	      file_name, xstrerror (errno));
    154  1.1  christos 
    155  1.1  christos       fclose (f_in);
    156  1.1  christos       f_in = NULL;
    157  1.1  christos       return;
    158  1.1  christos     }
    159  1.1  christos 
    160  1.1  christos   /* Check for an empty input file.  */
    161  1.1  christos   if (feof (f_in))
    162  1.1  christos     {
    163  1.1  christos       fclose (f_in);
    164  1.1  christos       f_in = NULL;
    165  1.1  christos       return;
    166  1.1  christos     }
    167  1.1  christos   gas_assert (c != EOF);
    168  1.1  christos 
    169  1.1  christos   if (c == '#')
    170  1.1  christos     {
    171  1.1  christos       /* Begins with comment, may not want to preprocess.  */
    172  1.1  christos       c = getc (f_in);
    173  1.1  christos       if (c == 'N')
    174  1.1  christos 	{
    175  1.1  christos 	  if (fgets (buf, sizeof (buf), f_in)
    176  1.1  christos 	      && !strncmp (buf, "O_APP", 5) && ISSPACE (buf[5]))
    177  1.1  christos 	    preprocess = 0;
    178  1.1  christos 	  if (!strchr (buf, '\n'))
    179  1.1  christos 	    ungetc ('#', f_in);	/* It was longer.  */
    180  1.1  christos 	  else
    181  1.1  christos 	    ungetc ('\n', f_in);
    182  1.1  christos 	}
    183  1.1  christos       else if (c == 'A')
    184  1.1  christos 	{
    185  1.1  christos 	  if (fgets (buf, sizeof (buf), f_in)
    186  1.1  christos 	      && !strncmp (buf, "PP", 2) && ISSPACE (buf[2]))
    187  1.1  christos 	    preprocess = 1;
    188  1.1  christos 	  if (!strchr (buf, '\n'))
    189  1.1  christos 	    ungetc ('#', f_in);
    190  1.1  christos 	  else
    191  1.1  christos 	    ungetc ('\n', f_in);
    192  1.1  christos 	}
    193  1.1  christos       else if (c == '\n')
    194  1.1  christos 	ungetc ('\n', f_in);
    195  1.1  christos       else
    196  1.1  christos 	ungetc ('#', f_in);
    197  1.1  christos     }
    198  1.1  christos   else
    199  1.1  christos     ungetc (c, f_in);
    200  1.1  christos }
    201  1.1  christos 
    202  1.1  christos /* Close input file.  */
    203  1.1  christos 
    204  1.1  christos void
    205  1.1  christos input_file_close (void)
    206  1.1  christos {
    207  1.1  christos   /* Don't close a null file pointer.  */
    208  1.1  christos   if (f_in != NULL)
    209  1.1  christos     fclose (f_in);
    210  1.1  christos 
    211  1.1  christos   f_in = 0;
    212  1.1  christos }
    213  1.1  christos 
    214  1.1  christos /* This function is passed to do_scrub_chars.  */
    215  1.1  christos 
    216  1.1  christos static size_t
    217  1.1  christos input_file_get (char *buf, size_t buflen)
    218  1.1  christos {
    219  1.1  christos   size_t size;
    220  1.1  christos 
    221  1.3  christos   if (feof (f_in))
    222  1.1  christos     return 0;
    223  1.1  christos 
    224  1.1  christos   size = fread (buf, sizeof (char), buflen, f_in);
    225  1.1  christos   if (ferror (f_in))
    226  1.1  christos     as_bad (_("can't read from %s: %s"), file_name, xstrerror (errno));
    227  1.1  christos   return size;
    228  1.1  christos }
    229  1.1  christos 
    230  1.1  christos /* Read a buffer from the input file.  */
    231  1.1  christos 
    232  1.1  christos char *
    233  1.1  christos input_file_give_next_buffer (char *where /* Where to place 1st character of new buffer.  */)
    234  1.1  christos {
    235  1.1  christos   char *return_value;		/* -> Last char of what we read, + 1.  */
    236  1.1  christos   size_t size;
    237  1.1  christos 
    238  1.1  christos   if (f_in == (FILE *) 0)
    239  1.1  christos     return 0;
    240  1.1  christos   /* fflush (stdin); could be done here if you want to synchronise
    241  1.1  christos      stdin and stdout, for the case where our input file is stdin.
    242  1.1  christos      Since the assembler shouldn't do any output to stdout, we
    243  1.1  christos      don't bother to synch output and input.  */
    244  1.1  christos   if (preprocess)
    245  1.1  christos     size = do_scrub_chars (input_file_get, where, BUFFER_SIZE);
    246  1.1  christos   else
    247  1.1  christos     size = input_file_get (where, BUFFER_SIZE);
    248  1.1  christos 
    249  1.1  christos   if (size)
    250  1.1  christos     return_value = where + size;
    251  1.1  christos   else
    252  1.1  christos     {
    253  1.1  christos       if (fclose (f_in))
    254  1.1  christos 	as_warn (_("can't close %s: %s"), file_name, xstrerror (errno));
    255  1.1  christos 
    256  1.1  christos       f_in = (FILE *) 0;
    257  1.1  christos       return_value = 0;
    258  1.1  christos     }
    259  1.1  christos 
    260                  return return_value;
    261                }
    262