Back to index

cell-binutils  2.17cvs20070401
input-file.c
Go to the documentation of this file.
00001 /* input_file.c - Deal with Input Files -
00002    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001,
00003    2002, 2003, 2005, 2006
00004    Free Software Foundation, Inc.
00005 
00006    This file is part of GAS, the GNU Assembler.
00007 
00008    GAS is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2, or (at your option)
00011    any later version.
00012 
00013    GAS is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with GAS; see the file COPYING.  If not, write to the Free
00020    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00021    02110-1301, USA.  */
00022 
00023 /* Confines all details of reading source bytes to this module.
00024    All O/S specific crocks should live here.
00025    What we lose in "efficiency" we gain in modularity.
00026    Note we don't need to #include the "as.h" file. No common coupling!  */
00027 
00028 #include "as.h"
00029 #include "input-file.h"
00030 #include "safe-ctype.h"
00031 
00032 static int input_file_get (char *, int);
00033 
00034 /* This variable is non-zero if the file currently being read should be
00035    preprocessed by app.  It is zero if the file can be read straight in.  */
00036 int preprocess = 0;
00037 
00038 /* This code opens a file, then delivers BUFFER_SIZE character
00039    chunks of the file on demand.
00040    BUFFER_SIZE is supposed to be a number chosen for speed.
00041    The caller only asks once what BUFFER_SIZE is, and asks before
00042    the nature of the input files (if any) is known.  */
00043 
00044 #define BUFFER_SIZE (32 * 1024)
00045 
00046 /* We use static data: the data area is not sharable.  */
00047 
00048 static FILE *f_in;
00049 static char *file_name;
00050 
00051 /* Struct for saving the state of this module for file includes.  */
00052 struct saved_file
00053   {
00054     FILE * f_in;
00055     char * file_name;
00056     int    preprocess;
00057     char * app_save;
00058   };
00059 
00060 /* These hooks accommodate most operating systems.  */
00061 
00062 void
00063 input_file_begin (void)
00064 {
00065   f_in = (FILE *) 0;
00066 }
00067 
00068 void
00069 input_file_end (void)
00070 {
00071 }
00072 
00073 /* Return BUFFER_SIZE.  */
00074 unsigned int
00075 input_file_buffer_size (void)
00076 {
00077   return (BUFFER_SIZE);
00078 }
00079 
00080 /* Push the state of our input, returning a pointer to saved info that
00081    can be restored with input_file_pop ().  */
00082 
00083 char *
00084 input_file_push (void)
00085 {
00086   register struct saved_file *saved;
00087 
00088   saved = (struct saved_file *) xmalloc (sizeof *saved);
00089 
00090   saved->f_in = f_in;
00091   saved->file_name = file_name;
00092   saved->preprocess = preprocess;
00093   if (preprocess)
00094     saved->app_save = app_push ();
00095 
00096   /* Initialize for new file.  */
00097   input_file_begin ();
00098 
00099   return (char *) saved;
00100 }
00101 
00102 void
00103 input_file_pop (char *arg)
00104 {
00105   register struct saved_file *saved = (struct saved_file *) arg;
00106 
00107   input_file_end ();        /* Close out old file.  */
00108 
00109   f_in = saved->f_in;
00110   file_name = saved->file_name;
00111   preprocess = saved->preprocess;
00112   if (preprocess)
00113     app_pop (saved->app_save);
00114 
00115   free (arg);
00116 }
00117 
00118 void
00119 input_file_open (char *filename, /* "" means use stdin. Must not be 0.  */
00120                int pre)
00121 {
00122   int c;
00123   char buf[80];
00124 
00125   preprocess = pre;
00126 
00127   assert (filename != 0);   /* Filename may not be NULL.  */
00128   if (filename[0])
00129     {
00130       f_in = fopen (filename, FOPEN_RT);
00131       file_name = filename;
00132     }
00133   else
00134     {
00135       /* Use stdin for the input file.  */
00136       f_in = stdin;
00137       /* For error messages.  */
00138       file_name = _("{standard input}");
00139     }
00140 
00141   if (f_in == NULL)
00142     {
00143       as_bad (_("can't open %s for reading: %s"),
00144              file_name, xstrerror (errno));
00145       return;
00146     }
00147 
00148   c = getc (f_in);
00149 
00150   if (ferror (f_in))
00151     {
00152       as_bad (_("can't read from %s: %s"),
00153              file_name, xstrerror (errno));
00154 
00155       fclose (f_in);
00156       f_in = NULL;
00157       return;
00158     }
00159 
00160   if (c == '#')
00161     {
00162       /* Begins with comment, may not want to preprocess.  */
00163       c = getc (f_in);
00164       if (c == 'N')
00165        {
00166          if (fgets (buf, sizeof (buf), f_in)
00167              && !strncmp (buf, "O_APP", 5) && ISSPACE (buf[5]))
00168            preprocess = 0;
00169          if (!strchr (buf, '\n'))
00170            ungetc ('#', f_in);     /* It was longer.  */
00171          else
00172            ungetc ('\n', f_in);
00173        }
00174       else if (c == 'A')
00175        {
00176          if (fgets (buf, sizeof (buf), f_in)
00177              && !strncmp (buf, "PP", 2) && ISSPACE (buf[2]))
00178            preprocess = 1;
00179          if (!strchr (buf, '\n'))
00180            ungetc ('#', f_in);
00181          else
00182            ungetc ('\n', f_in);
00183        }
00184       else if (c == '\n')
00185        ungetc ('\n', f_in);
00186       else
00187        ungetc ('#', f_in);
00188     }
00189   else
00190     ungetc (c, f_in);
00191 }
00192 
00193 /* Close input file.  */
00194 
00195 void
00196 input_file_close (void)
00197 {
00198   /* Don't close a null file pointer.  */
00199   if (f_in != NULL)
00200     fclose (f_in);
00201 
00202   f_in = 0;
00203 }
00204 
00205 /* This function is passed to do_scrub_chars.  */
00206 
00207 static int
00208 input_file_get (char *buf, int buflen)
00209 {
00210   int size;
00211 
00212   size = fread (buf, sizeof (char), buflen, f_in);
00213   if (size < 0)
00214     {
00215       as_bad (_("can't read from %s: %s"), file_name, xstrerror (errno));
00216       size = 0;
00217     }
00218   return size;
00219 }
00220 
00221 /* Read a buffer from the input file.  */
00222 
00223 char *
00224 input_file_give_next_buffer (char *where /* Where to place 1st character of new buffer.  */)
00225 {
00226   char *return_value;              /* -> Last char of what we read, + 1.  */
00227   register int size;
00228 
00229   if (f_in == (FILE *) 0)
00230     return 0;
00231   /* fflush (stdin); could be done here if you want to synchronise
00232      stdin and stdout, for the case where our input file is stdin.
00233      Since the assembler shouldn't do any output to stdout, we
00234      don't bother to synch output and input.  */
00235   if (preprocess)
00236     size = do_scrub_chars (input_file_get, where, BUFFER_SIZE);
00237   else
00238     size = fread (where, sizeof (char), BUFFER_SIZE, f_in);
00239   if (size < 0)
00240     {
00241       as_bad (_("can't read from %s: %s"), file_name, xstrerror (errno));
00242       size = 0;
00243     }
00244   if (size)
00245     return_value = where + size;
00246   else
00247     {
00248       if (fclose (f_in))
00249        as_warn (_("can't close %s: %s"), file_name, xstrerror (errno));
00250 
00251       f_in = (FILE *) 0;
00252       return_value = 0;
00253     }
00254 
00255   return return_value;
00256 }