input-file.c revision 130561
133965Sjdp/* input_file.c - Deal with Input Files -
2130561Sobrien   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2003
360484Sobrien   Free Software Foundation, Inc.
433965Sjdp
533965Sjdp   This file is part of GAS, the GNU Assembler.
633965Sjdp
733965Sjdp   GAS is free software; you can redistribute it and/or modify
833965Sjdp   it under the terms of the GNU General Public License as published by
933965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1033965Sjdp   any later version.
1133965Sjdp
1233965Sjdp   GAS is distributed in the hope that it will be useful,
1333965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1433965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965Sjdp   GNU General Public License for more details.
1633965Sjdp
1733965Sjdp   You should have received a copy of the GNU General Public License
1860484Sobrien   along with GAS; see the file COPYING.  If not, write to the Free
1960484Sobrien   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2060484Sobrien   02111-1307, USA.  */
2133965Sjdp
2289857Sobrien/* Confines all details of reading source bytes to this module.
2389857Sobrien   All O/S specific crocks should live here.
2489857Sobrien   What we lose in "efficiency" we gain in modularity.
2589857Sobrien   Note we don't need to #include the "as.h" file. No common coupling!  */
2633965Sjdp
2733965Sjdp#include <stdio.h>
2833965Sjdp#include <string.h>
29130561Sobrien#include <errno.h>
3033965Sjdp#include "as.h"
3133965Sjdp#include "input-file.h"
3289857Sobrien#include "safe-ctype.h"
3333965Sjdp
34130561Sobrienstatic int input_file_get (char *, int);
3533965Sjdp
3633965Sjdp/* This variable is non-zero if the file currently being read should be
3789857Sobrien   preprocessed by app.  It is zero if the file can be read straight in.  */
3833965Sjdpint preprocess = 0;
3933965Sjdp
4089857Sobrien/* This code opens a file, then delivers BUFFER_SIZE character
4189857Sobrien   chunks of the file on demand.
4289857Sobrien   BUFFER_SIZE is supposed to be a number chosen for speed.
4389857Sobrien   The caller only asks once what BUFFER_SIZE is, and asks before
4489857Sobrien   the nature of the input files (if any) is known.  */
4533965Sjdp
4633965Sjdp#define BUFFER_SIZE (32 * 1024)
4733965Sjdp
4889857Sobrien/* We use static data: the data area is not sharable.  */
4933965Sjdp
5033965Sjdpstatic FILE *f_in;
5133965Sjdpstatic char *file_name;
5233965Sjdp
5333965Sjdp/* Struct for saving the state of this module for file includes.  */
5489857Sobrienstruct saved_file
5589857Sobrien  {
5689857Sobrien    FILE * f_in;
5789857Sobrien    char * file_name;
5889857Sobrien    int    preprocess;
5989857Sobrien    char * app_save;
6089857Sobrien  };
6133965Sjdp
62130561Sobrien/* These hooks accommodate most operating systems.  */
6333965Sjdp
6477298Sobrienvoid
65130561Sobrieninput_file_begin (void)
6633965Sjdp{
6733965Sjdp  f_in = (FILE *) 0;
6833965Sjdp}
6933965Sjdp
7077298Sobrienvoid
71130561Sobrieninput_file_end (void)
7233965Sjdp{
7333965Sjdp}
7433965Sjdp
7577298Sobrien/* Return BUFFER_SIZE.  */
7677298Sobrienunsigned int
77130561Sobrieninput_file_buffer_size (void)
7833965Sjdp{
7933965Sjdp  return (BUFFER_SIZE);
8033965Sjdp}
8133965Sjdp
8277298Sobrienint
83130561Sobrieninput_file_is_open (void)
8433965Sjdp{
8533965Sjdp  return f_in != (FILE *) 0;
8633965Sjdp}
8733965Sjdp
8833965Sjdp/* Push the state of our input, returning a pointer to saved info that
8933965Sjdp   can be restored with input_file_pop ().  */
9089857Sobrien
9133965Sjdpchar *
92130561Sobrieninput_file_push (void)
9333965Sjdp{
9433965Sjdp  register struct saved_file *saved;
9533965Sjdp
9633965Sjdp  saved = (struct saved_file *) xmalloc (sizeof *saved);
9733965Sjdp
9833965Sjdp  saved->f_in = f_in;
9933965Sjdp  saved->file_name = file_name;
10033965Sjdp  saved->preprocess = preprocess;
10133965Sjdp  if (preprocess)
10233965Sjdp    saved->app_save = app_push ();
10333965Sjdp
10489857Sobrien  /* Initialize for new file.  */
10589857Sobrien  input_file_begin ();
10633965Sjdp
10733965Sjdp  return (char *) saved;
10833965Sjdp}
10933965Sjdp
11033965Sjdpvoid
111130561Sobrieninput_file_pop (char *arg)
11233965Sjdp{
11333965Sjdp  register struct saved_file *saved = (struct saved_file *) arg;
11433965Sjdp
11589857Sobrien  input_file_end ();		/* Close out old file.  */
11633965Sjdp
11733965Sjdp  f_in = saved->f_in;
11833965Sjdp  file_name = saved->file_name;
11933965Sjdp  preprocess = saved->preprocess;
12033965Sjdp  if (preprocess)
12133965Sjdp    app_pop (saved->app_save);
12233965Sjdp
12333965Sjdp  free (arg);
12433965Sjdp}
12533965Sjdp
12633965Sjdpvoid
127130561Sobrieninput_file_open (char *filename, /* "" means use stdin. Must not be 0.  */
128130561Sobrien		 int pre)
12933965Sjdp{
13033965Sjdp  int c;
13133965Sjdp  char buf[80];
13233965Sjdp
13333965Sjdp  preprocess = pre;
13433965Sjdp
13577298Sobrien  assert (filename != 0);	/* Filename may not be NULL.  */
13633965Sjdp  if (filename[0])
137130561Sobrien    {
13889857Sobrien      f_in = fopen (filename, FOPEN_RT);
13933965Sjdp      file_name = filename;
14033965Sjdp    }
14133965Sjdp  else
142130561Sobrien    {
143130561Sobrien      /* Use stdin for the input file.  */
14433965Sjdp      f_in = stdin;
145130561Sobrien      /* For error messages.  */
146130561Sobrien      file_name = _("{standard input}");
14733965Sjdp    }
148130561Sobrien
149130561Sobrien  if (f_in)
150130561Sobrien    c = getc (f_in);
151130561Sobrien
152130561Sobrien  if (f_in == NULL || ferror (f_in))
15333965Sjdp    {
154130561Sobrien#ifdef BFD_ASSEMBLER
155130561Sobrien      bfd_set_error (bfd_error_system_call);
156130561Sobrien#endif
157130561Sobrien      as_perror (_("Can't open %s for reading"), file_name);
158130561Sobrien
159130561Sobrien      if (f_in)
160130561Sobrien	{
161130561Sobrien	  fclose (f_in);
162130561Sobrien	  f_in = NULL;
163130561Sobrien	}
16433965Sjdp      return;
16533965Sjdp    }
16633965Sjdp
16733965Sjdp  if (c == '#')
16889857Sobrien    {
16989857Sobrien      /* Begins with comment, may not want to preprocess.  */
17033965Sjdp      c = getc (f_in);
17133965Sjdp      if (c == 'N')
172104834Sobrien	{
173104834Sobrien	  fgets (buf, 80, f_in);
174104834Sobrien	  if (!strncmp (buf, "O_APP", 5) && ISSPACE (buf[5]))
175104834Sobrien	    preprocess = 0;
176104834Sobrien	  if (!strchr (buf, '\n'))
177104834Sobrien	    ungetc ('#', f_in);	/* It was longer.  */
178104834Sobrien	  else
179104834Sobrien	    ungetc ('\n', f_in);
180104834Sobrien	}
18189857Sobrien      else if (c == 'A')
182104834Sobrien	{
183104834Sobrien	  fgets (buf, 80, f_in);
184104834Sobrien	  if (!strncmp (buf, "PP", 2) && ISSPACE (buf[2]))
185104834Sobrien	    preprocess = 1;
186104834Sobrien	  if (!strchr (buf, '\n'))
187104834Sobrien	    ungetc ('#', f_in);
188104834Sobrien	  else
189104834Sobrien	    ungetc ('\n', f_in);
190104834Sobrien	}
19133965Sjdp      else if (c == '\n')
192104834Sobrien	ungetc ('\n', f_in);
19333965Sjdp      else
194104834Sobrien	ungetc ('#', f_in);
19533965Sjdp    }
19633965Sjdp  else
19733965Sjdp    ungetc (c, f_in);
19833965Sjdp}
19933965Sjdp
20033965Sjdp/* Close input file.  */
20189857Sobrien
20277298Sobrienvoid
203130561Sobrieninput_file_close (void)
20433965Sjdp{
20589857Sobrien  /* Don't close a null file pointer.  */
20633965Sjdp  if (f_in != NULL)
20789857Sobrien    fclose (f_in);
20889857Sobrien
20933965Sjdp  f_in = 0;
21077298Sobrien}
21133965Sjdp
21233965Sjdp/* This function is passed to do_scrub_chars.  */
21333965Sjdp
21433965Sjdpstatic int
215130561Sobrieninput_file_get (char *buf, int buflen)
21633965Sjdp{
21733965Sjdp  int size;
21833965Sjdp
21960484Sobrien  size = fread (buf, sizeof (char), buflen, f_in);
22033965Sjdp  if (size < 0)
22133965Sjdp    {
222130561Sobrien#ifdef BFD_ASSEMBLER
223130561Sobrien      bfd_set_error (bfd_error_system_call);
224130561Sobrien#endif
22560484Sobrien      as_perror (_("Can't read from %s"), file_name);
22633965Sjdp      size = 0;
22733965Sjdp    }
22833965Sjdp  return size;
22933965Sjdp}
23033965Sjdp
23133965Sjdp/* Read a buffer from the input file.  */
23233965Sjdp
23333965Sjdpchar *
234130561Sobrieninput_file_give_next_buffer (char *where /* Where to place 1st character of new buffer.  */)
23533965Sjdp{
23677298Sobrien  char *return_value;		/* -> Last char of what we read, + 1.  */
23733965Sjdp  register int size;
23833965Sjdp
23933965Sjdp  if (f_in == (FILE *) 0)
24033965Sjdp    return 0;
24189857Sobrien  /* fflush (stdin); could be done here if you want to synchronise
24289857Sobrien     stdin and stdout, for the case where our input file is stdin.
24389857Sobrien     Since the assembler shouldn't do any output to stdout, we
24489857Sobrien     don't bother to synch output and input.  */
24533965Sjdp  if (preprocess)
24633965Sjdp    size = do_scrub_chars (input_file_get, where, BUFFER_SIZE);
24733965Sjdp  else
24833965Sjdp    size = fread (where, sizeof (char), BUFFER_SIZE, f_in);
24933965Sjdp  if (size < 0)
25033965Sjdp    {
251130561Sobrien#ifdef BFD_ASSEMBLER
252130561Sobrien      bfd_set_error (bfd_error_system_call);
253130561Sobrien#endif
25460484Sobrien      as_perror (_("Can't read from %s"), file_name);
25533965Sjdp      size = 0;
25633965Sjdp    }
25733965Sjdp  if (size)
25833965Sjdp    return_value = where + size;
25933965Sjdp  else
26033965Sjdp    {
26133965Sjdp      if (fclose (f_in))
262130561Sobrien	{
263130561Sobrien#ifdef BFD_ASSEMBLER
264130561Sobrien	  bfd_set_error (bfd_error_system_call);
265130561Sobrien#endif
266130561Sobrien	  as_perror (_("Can't close %s"), file_name);
267130561Sobrien	}
26833965Sjdp      f_in = (FILE *) 0;
26933965Sjdp      return_value = 0;
27033965Sjdp    }
27189857Sobrien
27289857Sobrien  return return_value;
27333965Sjdp}
274