133965Sjdp/* input_file.c - Deal with Input Files -
2218822Sdim   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001,
3218822Sdim   2002, 2003, 2005, 2006
460484Sobrien   Free Software Foundation, Inc.
533965Sjdp
633965Sjdp   This file is part of GAS, the GNU Assembler.
733965Sjdp
833965Sjdp   GAS is free software; you can redistribute it and/or modify
933965Sjdp   it under the terms of the GNU General Public License as published by
1033965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1133965Sjdp   any later version.
1233965Sjdp
1333965Sjdp   GAS is distributed in the hope that it will be useful,
1433965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1533965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1633965Sjdp   GNU General Public License for more details.
1733965Sjdp
1833965Sjdp   You should have received a copy of the GNU General Public License
1960484Sobrien   along with GAS; see the file COPYING.  If not, write to the Free
20218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21218822Sdim   02110-1301, USA.  */
2233965Sjdp
2389857Sobrien/* Confines all details of reading source bytes to this module.
2489857Sobrien   All O/S specific crocks should live here.
2589857Sobrien   What we lose in "efficiency" we gain in modularity.
2689857Sobrien   Note we don't need to #include the "as.h" file. No common coupling!  */
2733965Sjdp
2833965Sjdp#include "as.h"
2933965Sjdp#include "input-file.h"
3089857Sobrien#include "safe-ctype.h"
3133965Sjdp
32130561Sobrienstatic int input_file_get (char *, int);
3333965Sjdp
3433965Sjdp/* This variable is non-zero if the file currently being read should be
3589857Sobrien   preprocessed by app.  It is zero if the file can be read straight in.  */
3633965Sjdpint preprocess = 0;
3733965Sjdp
3889857Sobrien/* This code opens a file, then delivers BUFFER_SIZE character
3989857Sobrien   chunks of the file on demand.
4089857Sobrien   BUFFER_SIZE is supposed to be a number chosen for speed.
4189857Sobrien   The caller only asks once what BUFFER_SIZE is, and asks before
4289857Sobrien   the nature of the input files (if any) is known.  */
4333965Sjdp
4433965Sjdp#define BUFFER_SIZE (32 * 1024)
4533965Sjdp
4689857Sobrien/* We use static data: the data area is not sharable.  */
4733965Sjdp
4833965Sjdpstatic FILE *f_in;
4933965Sjdpstatic char *file_name;
5033965Sjdp
5133965Sjdp/* Struct for saving the state of this module for file includes.  */
5289857Sobrienstruct saved_file
5389857Sobrien  {
5489857Sobrien    FILE * f_in;
5589857Sobrien    char * file_name;
5689857Sobrien    int    preprocess;
5789857Sobrien    char * app_save;
5889857Sobrien  };
5933965Sjdp
60130561Sobrien/* These hooks accommodate most operating systems.  */
6133965Sjdp
6277298Sobrienvoid
63130561Sobrieninput_file_begin (void)
6433965Sjdp{
6533965Sjdp  f_in = (FILE *) 0;
6633965Sjdp}
6733965Sjdp
6877298Sobrienvoid
69130561Sobrieninput_file_end (void)
7033965Sjdp{
7133965Sjdp}
7233965Sjdp
7377298Sobrien/* Return BUFFER_SIZE.  */
7477298Sobrienunsigned int
75130561Sobrieninput_file_buffer_size (void)
7633965Sjdp{
7733965Sjdp  return (BUFFER_SIZE);
7833965Sjdp}
7933965Sjdp
8033965Sjdp/* Push the state of our input, returning a pointer to saved info that
8133965Sjdp   can be restored with input_file_pop ().  */
8289857Sobrien
8333965Sjdpchar *
84130561Sobrieninput_file_push (void)
8533965Sjdp{
8633965Sjdp  register struct saved_file *saved;
8733965Sjdp
8833965Sjdp  saved = (struct saved_file *) xmalloc (sizeof *saved);
8933965Sjdp
9033965Sjdp  saved->f_in = f_in;
9133965Sjdp  saved->file_name = file_name;
9233965Sjdp  saved->preprocess = preprocess;
9333965Sjdp  if (preprocess)
9433965Sjdp    saved->app_save = app_push ();
9533965Sjdp
9689857Sobrien  /* Initialize for new file.  */
9789857Sobrien  input_file_begin ();
9833965Sjdp
9933965Sjdp  return (char *) saved;
10033965Sjdp}
10133965Sjdp
10233965Sjdpvoid
103130561Sobrieninput_file_pop (char *arg)
10433965Sjdp{
10533965Sjdp  register struct saved_file *saved = (struct saved_file *) arg;
10633965Sjdp
10789857Sobrien  input_file_end ();		/* Close out old file.  */
10833965Sjdp
10933965Sjdp  f_in = saved->f_in;
11033965Sjdp  file_name = saved->file_name;
11133965Sjdp  preprocess = saved->preprocess;
11233965Sjdp  if (preprocess)
11333965Sjdp    app_pop (saved->app_save);
11433965Sjdp
11533965Sjdp  free (arg);
11633965Sjdp}
11733965Sjdp
11833965Sjdpvoid
119130561Sobrieninput_file_open (char *filename, /* "" means use stdin. Must not be 0.  */
120130561Sobrien		 int pre)
12133965Sjdp{
12233965Sjdp  int c;
12333965Sjdp  char buf[80];
12433965Sjdp
12533965Sjdp  preprocess = pre;
12633965Sjdp
12777298Sobrien  assert (filename != 0);	/* Filename may not be NULL.  */
12833965Sjdp  if (filename[0])
129130561Sobrien    {
13089857Sobrien      f_in = fopen (filename, FOPEN_RT);
13133965Sjdp      file_name = filename;
13233965Sjdp    }
13333965Sjdp  else
134130561Sobrien    {
135130561Sobrien      /* Use stdin for the input file.  */
13633965Sjdp      f_in = stdin;
137130561Sobrien      /* For error messages.  */
138130561Sobrien      file_name = _("{standard input}");
13933965Sjdp    }
140130561Sobrien
141218822Sdim  if (f_in == NULL)
142218822Sdim    {
143218822Sdim      as_bad (_("can't open %s for reading: %s"),
144218822Sdim	      file_name, xstrerror (errno));
145218822Sdim      return;
146218822Sdim    }
147130561Sobrien
148218822Sdim  c = getc (f_in);
149218822Sdim
150218822Sdim  if (ferror (f_in))
15133965Sjdp    {
152218822Sdim      as_bad (_("can't read from %s: %s"),
153218822Sdim	      file_name, xstrerror (errno));
154130561Sobrien
155218822Sdim      fclose (f_in);
156218822Sdim      f_in = NULL;
15733965Sjdp      return;
15833965Sjdp    }
15933965Sjdp
16033965Sjdp  if (c == '#')
16189857Sobrien    {
16289857Sobrien      /* Begins with comment, may not want to preprocess.  */
16333965Sjdp      c = getc (f_in);
16433965Sjdp      if (c == 'N')
165104834Sobrien	{
166218822Sdim	  if (fgets (buf, sizeof (buf), f_in)
167218822Sdim	      && !strncmp (buf, "O_APP", 5) && ISSPACE (buf[5]))
168104834Sobrien	    preprocess = 0;
169104834Sobrien	  if (!strchr (buf, '\n'))
170104834Sobrien	    ungetc ('#', f_in);	/* It was longer.  */
171104834Sobrien	  else
172104834Sobrien	    ungetc ('\n', f_in);
173104834Sobrien	}
17489857Sobrien      else if (c == 'A')
175104834Sobrien	{
176218822Sdim	  if (fgets (buf, sizeof (buf), f_in)
177218822Sdim	      && !strncmp (buf, "PP", 2) && ISSPACE (buf[2]))
178104834Sobrien	    preprocess = 1;
179104834Sobrien	  if (!strchr (buf, '\n'))
180104834Sobrien	    ungetc ('#', f_in);
181104834Sobrien	  else
182104834Sobrien	    ungetc ('\n', f_in);
183104834Sobrien	}
18433965Sjdp      else if (c == '\n')
185104834Sobrien	ungetc ('\n', f_in);
18633965Sjdp      else
187104834Sobrien	ungetc ('#', f_in);
18833965Sjdp    }
18933965Sjdp  else
19033965Sjdp    ungetc (c, f_in);
19133965Sjdp}
19233965Sjdp
19333965Sjdp/* Close input file.  */
19489857Sobrien
19577298Sobrienvoid
196130561Sobrieninput_file_close (void)
19733965Sjdp{
19889857Sobrien  /* Don't close a null file pointer.  */
19933965Sjdp  if (f_in != NULL)
20089857Sobrien    fclose (f_in);
20189857Sobrien
20233965Sjdp  f_in = 0;
20377298Sobrien}
20433965Sjdp
20533965Sjdp/* This function is passed to do_scrub_chars.  */
20633965Sjdp
20733965Sjdpstatic int
208130561Sobrieninput_file_get (char *buf, int buflen)
20933965Sjdp{
21033965Sjdp  int size;
21133965Sjdp
21260484Sobrien  size = fread (buf, sizeof (char), buflen, f_in);
21333965Sjdp  if (size < 0)
21433965Sjdp    {
215218822Sdim      as_bad (_("can't read from %s: %s"), file_name, xstrerror (errno));
21633965Sjdp      size = 0;
21733965Sjdp    }
21833965Sjdp  return size;
21933965Sjdp}
22033965Sjdp
22133965Sjdp/* Read a buffer from the input file.  */
22233965Sjdp
22333965Sjdpchar *
224130561Sobrieninput_file_give_next_buffer (char *where /* Where to place 1st character of new buffer.  */)
22533965Sjdp{
22677298Sobrien  char *return_value;		/* -> Last char of what we read, + 1.  */
22733965Sjdp  register int size;
22833965Sjdp
22933965Sjdp  if (f_in == (FILE *) 0)
23033965Sjdp    return 0;
23189857Sobrien  /* fflush (stdin); could be done here if you want to synchronise
23289857Sobrien     stdin and stdout, for the case where our input file is stdin.
23389857Sobrien     Since the assembler shouldn't do any output to stdout, we
23489857Sobrien     don't bother to synch output and input.  */
23533965Sjdp  if (preprocess)
23633965Sjdp    size = do_scrub_chars (input_file_get, where, BUFFER_SIZE);
23733965Sjdp  else
23833965Sjdp    size = fread (where, sizeof (char), BUFFER_SIZE, f_in);
23933965Sjdp  if (size < 0)
24033965Sjdp    {
241218822Sdim      as_bad (_("can't read from %s: %s"), file_name, xstrerror (errno));
24233965Sjdp      size = 0;
24333965Sjdp    }
24433965Sjdp  if (size)
24533965Sjdp    return_value = where + size;
24633965Sjdp  else
24733965Sjdp    {
24833965Sjdp      if (fclose (f_in))
249218822Sdim	as_warn (_("can't close %s: %s"), file_name, xstrerror (errno));
250218822Sdim
25133965Sjdp      f_in = (FILE *) 0;
25233965Sjdp      return_value = 0;
25333965Sjdp    }
25489857Sobrien
25589857Sobrien  return return_value;
25633965Sjdp}
257