input-file.c revision 89857
133965Sjdp/* input_file.c - Deal with Input Files -
289857Sobrien   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001
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>
2933965Sjdp#include "as.h"
3033965Sjdp#include "input-file.h"
3189857Sobrien#include "safe-ctype.h"
3233965Sjdp
3360484Sobrienstatic int input_file_get PARAMS ((char *, int));
3433965Sjdp
3533965Sjdp/* This variable is non-zero if the file currently being read should be
3689857Sobrien   preprocessed by app.  It is zero if the file can be read straight in.  */
3733965Sjdpint preprocess = 0;
3833965Sjdp
3989857Sobrien/* This code opens a file, then delivers BUFFER_SIZE character
4089857Sobrien   chunks of the file on demand.
4189857Sobrien   BUFFER_SIZE is supposed to be a number chosen for speed.
4289857Sobrien   The caller only asks once what BUFFER_SIZE is, and asks before
4389857Sobrien   the nature of the input files (if any) is known.  */
4433965Sjdp
4533965Sjdp#define BUFFER_SIZE (32 * 1024)
4633965Sjdp
4789857Sobrien/* We use static data: the data area is not sharable.  */
4833965Sjdp
4933965Sjdpstatic FILE *f_in;
5033965Sjdpstatic char *file_name;
5133965Sjdp
5233965Sjdp/* Struct for saving the state of this module for file includes.  */
5389857Sobrienstruct saved_file
5489857Sobrien  {
5589857Sobrien    FILE * f_in;
5689857Sobrien    char * file_name;
5789857Sobrien    int    preprocess;
5889857Sobrien    char * app_save;
5989857Sobrien  };
6033965Sjdp
6177298Sobrien/* These hooks accomodate most operating systems.  */
6233965Sjdp
6377298Sobrienvoid
6433965Sjdpinput_file_begin ()
6533965Sjdp{
6633965Sjdp  f_in = (FILE *) 0;
6733965Sjdp}
6833965Sjdp
6977298Sobrienvoid
7033965Sjdpinput_file_end ()
7133965Sjdp{
7233965Sjdp}
7333965Sjdp
7477298Sobrien/* Return BUFFER_SIZE.  */
7577298Sobrienunsigned int
7633965Sjdpinput_file_buffer_size ()
7733965Sjdp{
7833965Sjdp  return (BUFFER_SIZE);
7933965Sjdp}
8033965Sjdp
8177298Sobrienint
8233965Sjdpinput_file_is_open ()
8333965Sjdp{
8433965Sjdp  return f_in != (FILE *) 0;
8533965Sjdp}
8633965Sjdp
8733965Sjdp/* Push the state of our input, returning a pointer to saved info that
8833965Sjdp   can be restored with input_file_pop ().  */
8989857Sobrien
9033965Sjdpchar *
9133965Sjdpinput_file_push ()
9233965Sjdp{
9333965Sjdp  register struct saved_file *saved;
9433965Sjdp
9533965Sjdp  saved = (struct saved_file *) xmalloc (sizeof *saved);
9633965Sjdp
9733965Sjdp  saved->f_in = f_in;
9833965Sjdp  saved->file_name = file_name;
9933965Sjdp  saved->preprocess = preprocess;
10033965Sjdp  if (preprocess)
10133965Sjdp    saved->app_save = app_push ();
10233965Sjdp
10389857Sobrien  /* Initialize for new file.  */
10489857Sobrien  input_file_begin ();
10533965Sjdp
10633965Sjdp  return (char *) saved;
10733965Sjdp}
10833965Sjdp
10933965Sjdpvoid
11033965Sjdpinput_file_pop (arg)
11133965Sjdp     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
12733965Sjdpinput_file_open (filename, pre)
12877298Sobrien     char *filename;		/* "" means use stdin. Must not be 0.  */
12933965Sjdp     int pre;
13033965Sjdp{
13133965Sjdp  int c;
13233965Sjdp  char buf[80];
13333965Sjdp
13433965Sjdp  preprocess = pre;
13533965Sjdp
13677298Sobrien  assert (filename != 0);	/* Filename may not be NULL.  */
13733965Sjdp  if (filename[0])
13877298Sobrien    {				/* We have a file name. Suck it and see.  */
13989857Sobrien      f_in = fopen (filename, FOPEN_RT);
14033965Sjdp      file_name = filename;
14133965Sjdp    }
14233965Sjdp  else
14377298Sobrien    {				/* use stdin for the input file.  */
14433965Sjdp      f_in = stdin;
14577298Sobrien      file_name = _("{standard input}");	/* For error messages.  */
14633965Sjdp    }
14733965Sjdp  if (f_in == (FILE *) 0)
14833965Sjdp    {
14989857Sobrien      as_bad (_("can't open %s for reading"), file_name);
15033965Sjdp      as_perror ("%s", file_name);
15133965Sjdp      return;
15233965Sjdp    }
15333965Sjdp
15433965Sjdp  c = getc (f_in);
15533965Sjdp  if (c == '#')
15689857Sobrien    {
15789857Sobrien      /* Begins with comment, may not want to preprocess.  */
15833965Sjdp      c = getc (f_in);
15933965Sjdp      if (c == 'N')
16089857Sobrien        {
16189857Sobrien          fgets (buf, 80, f_in);
16289857Sobrien          if (!strncmp (buf, "O_APP", 5) && ISSPACE (buf[5]))
16389857Sobrien            preprocess = 0;
16489857Sobrien          if (!strchr (buf, '\n'))
16589857Sobrien            ungetc ('#', f_in);	/* It was longer.  */
16689857Sobrien          else
16789857Sobrien            ungetc ('\n', f_in);
16889857Sobrien        }
16989857Sobrien      else if (c == 'A')
17089857Sobrien        {
17189857Sobrien          fgets (buf, 80, f_in);
17289857Sobrien          if (!strncmp (buf, "PP", 2) && ISSPACE (buf[2]))
17389857Sobrien            preprocess = 1;
17489857Sobrien          if (!strchr (buf, '\n'))
17589857Sobrien            ungetc ('#', f_in);
17689857Sobrien          else
17789857Sobrien            ungetc ('\n', f_in);
17889857Sobrien        }
17933965Sjdp      else if (c == '\n')
18089857Sobrien        ungetc ('\n', f_in);
18133965Sjdp      else
18289857Sobrien        ungetc ('#', f_in);
18333965Sjdp    }
18433965Sjdp  else
18533965Sjdp    ungetc (c, f_in);
18633965Sjdp}
18733965Sjdp
18833965Sjdp/* Close input file.  */
18989857Sobrien
19077298Sobrienvoid
19133965Sjdpinput_file_close ()
19233965Sjdp{
19389857Sobrien  /* Don't close a null file pointer.  */
19433965Sjdp  if (f_in != NULL)
19589857Sobrien    fclose (f_in);
19689857Sobrien
19733965Sjdp  f_in = 0;
19877298Sobrien}
19933965Sjdp
20033965Sjdp/* This function is passed to do_scrub_chars.  */
20133965Sjdp
20233965Sjdpstatic int
20360484Sobrieninput_file_get (buf, buflen)
20460484Sobrien     char *buf;
20560484Sobrien     int buflen;
20633965Sjdp{
20733965Sjdp  int size;
20833965Sjdp
20960484Sobrien  size = fread (buf, sizeof (char), buflen, f_in);
21033965Sjdp  if (size < 0)
21133965Sjdp    {
21260484Sobrien      as_perror (_("Can't read from %s"), file_name);
21333965Sjdp      size = 0;
21433965Sjdp    }
21533965Sjdp  return size;
21633965Sjdp}
21733965Sjdp
21833965Sjdp/* Read a buffer from the input file.  */
21933965Sjdp
22033965Sjdpchar *
22133965Sjdpinput_file_give_next_buffer (where)
22277298Sobrien     char *where;		/* Where to place 1st character of new buffer.  */
22333965Sjdp{
22477298Sobrien  char *return_value;		/* -> Last char of what we read, + 1.  */
22533965Sjdp  register int size;
22633965Sjdp
22733965Sjdp  if (f_in == (FILE *) 0)
22833965Sjdp    return 0;
22989857Sobrien  /* fflush (stdin); could be done here if you want to synchronise
23089857Sobrien     stdin and stdout, for the case where our input file is stdin.
23189857Sobrien     Since the assembler shouldn't do any output to stdout, we
23289857Sobrien     don't bother to synch output and input.  */
23333965Sjdp  if (preprocess)
23433965Sjdp    size = do_scrub_chars (input_file_get, where, BUFFER_SIZE);
23533965Sjdp  else
23633965Sjdp    size = fread (where, sizeof (char), BUFFER_SIZE, f_in);
23733965Sjdp  if (size < 0)
23833965Sjdp    {
23960484Sobrien      as_perror (_("Can't read from %s"), file_name);
24033965Sjdp      size = 0;
24133965Sjdp    }
24233965Sjdp  if (size)
24333965Sjdp    return_value = where + size;
24433965Sjdp  else
24533965Sjdp    {
24633965Sjdp      if (fclose (f_in))
24760484Sobrien	as_perror (_("Can't close %s"), file_name);
24833965Sjdp      f_in = (FILE *) 0;
24933965Sjdp      return_value = 0;
25033965Sjdp    }
25189857Sobrien
25289857Sobrien  return return_value;
25333965Sjdp}
254