xref: /openbsd-src/gnu/usr.bin/binutils/gas/input-file.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
12159047fSniklas /* input_file.c - Deal with Input Files -
2*007c2a45Smiod    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2003
3f7cc78ecSespie    Free Software Foundation, Inc.
42159047fSniklas 
52159047fSniklas    This file is part of GAS, the GNU Assembler.
62159047fSniklas 
72159047fSniklas    GAS is free software; you can redistribute it and/or modify
82159047fSniklas    it under the terms of the GNU General Public License as published by
92159047fSniklas    the Free Software Foundation; either version 2, or (at your option)
102159047fSniklas    any later version.
112159047fSniklas 
122159047fSniklas    GAS is distributed in the hope that it will be useful,
132159047fSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
142159047fSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
152159047fSniklas    GNU General Public License for more details.
162159047fSniklas 
172159047fSniklas    You should have received a copy of the GNU General Public License
18f7cc78ecSespie    along with GAS; see the file COPYING.  If not, write to the Free
19f7cc78ecSespie    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20f7cc78ecSespie    02111-1307, USA.  */
212159047fSniklas 
22c074d1c9Sdrahn /* Confines all details of reading source bytes to this module.
23c074d1c9Sdrahn    All O/S specific crocks should live here.
24c074d1c9Sdrahn    What we lose in "efficiency" we gain in modularity.
25c074d1c9Sdrahn    Note we don't need to #include the "as.h" file. No common coupling!  */
262159047fSniklas 
272159047fSniklas #include <stdio.h>
282159047fSniklas #include <string.h>
29*007c2a45Smiod #include <errno.h>
302159047fSniklas #include "as.h"
312159047fSniklas #include "input-file.h"
32c074d1c9Sdrahn #include "safe-ctype.h"
332159047fSniklas 
34*007c2a45Smiod static int input_file_get (char *, int);
352159047fSniklas 
362159047fSniklas /* This variable is non-zero if the file currently being read should be
37c074d1c9Sdrahn    preprocessed by app.  It is zero if the file can be read straight in.  */
382159047fSniklas int preprocess = 0;
392159047fSniklas 
40c074d1c9Sdrahn /* This code opens a file, then delivers BUFFER_SIZE character
41c074d1c9Sdrahn    chunks of the file on demand.
42c074d1c9Sdrahn    BUFFER_SIZE is supposed to be a number chosen for speed.
43c074d1c9Sdrahn    The caller only asks once what BUFFER_SIZE is, and asks before
44c074d1c9Sdrahn    the nature of the input files (if any) is known.  */
452159047fSniklas 
462159047fSniklas #define BUFFER_SIZE (32 * 1024)
472159047fSniklas 
48c074d1c9Sdrahn /* We use static data: the data area is not sharable.  */
492159047fSniklas 
502159047fSniklas static FILE *f_in;
512159047fSniklas static char *file_name;
522159047fSniklas 
532159047fSniklas /* Struct for saving the state of this module for file includes.  */
54c074d1c9Sdrahn struct saved_file
55c074d1c9Sdrahn   {
562159047fSniklas     FILE * f_in;
572159047fSniklas     char * file_name;
582159047fSniklas     int    preprocess;
592159047fSniklas     char * app_save;
602159047fSniklas   };
612159047fSniklas 
62*007c2a45Smiod /* These hooks accommodate most operating systems.  */
632159047fSniklas 
642159047fSniklas void
input_file_begin(void)65*007c2a45Smiod input_file_begin (void)
662159047fSniklas {
672159047fSniklas   f_in = (FILE *) 0;
682159047fSniklas }
692159047fSniklas 
702159047fSniklas void
input_file_end(void)71*007c2a45Smiod input_file_end (void)
722159047fSniklas {
732159047fSniklas }
742159047fSniklas 
752159047fSniklas /* Return BUFFER_SIZE.  */
762159047fSniklas unsigned int
input_file_buffer_size(void)77*007c2a45Smiod input_file_buffer_size (void)
782159047fSniklas {
792159047fSniklas   return (BUFFER_SIZE);
802159047fSniklas }
812159047fSniklas 
822159047fSniklas int
input_file_is_open(void)83*007c2a45Smiod input_file_is_open (void)
842159047fSniklas {
852159047fSniklas   return f_in != (FILE *) 0;
862159047fSniklas }
872159047fSniklas 
882159047fSniklas /* Push the state of our input, returning a pointer to saved info that
892159047fSniklas    can be restored with input_file_pop ().  */
90c074d1c9Sdrahn 
912159047fSniklas char *
input_file_push(void)92*007c2a45Smiod input_file_push (void)
932159047fSniklas {
942159047fSniklas   register struct saved_file *saved;
952159047fSniklas 
962159047fSniklas   saved = (struct saved_file *) xmalloc (sizeof *saved);
972159047fSniklas 
982159047fSniklas   saved->f_in = f_in;
992159047fSniklas   saved->file_name = file_name;
1002159047fSniklas   saved->preprocess = preprocess;
1012159047fSniklas   if (preprocess)
1022159047fSniklas     saved->app_save = app_push ();
1032159047fSniklas 
104c074d1c9Sdrahn   /* Initialize for new file.  */
105c074d1c9Sdrahn   input_file_begin ();
1062159047fSniklas 
1072159047fSniklas   return (char *) saved;
1082159047fSniklas }
1092159047fSniklas 
1102159047fSniklas void
input_file_pop(char * arg)111*007c2a45Smiod input_file_pop (char *arg)
1122159047fSniklas {
1132159047fSniklas   register struct saved_file *saved = (struct saved_file *) arg;
1142159047fSniklas 
115c074d1c9Sdrahn   input_file_end ();		/* Close out old file.  */
1162159047fSniklas 
1172159047fSniklas   f_in = saved->f_in;
1182159047fSniklas   file_name = saved->file_name;
1192159047fSniklas   preprocess = saved->preprocess;
1202159047fSniklas   if (preprocess)
1212159047fSniklas     app_pop (saved->app_save);
1222159047fSniklas 
1232159047fSniklas   free (arg);
1242159047fSniklas }
1252159047fSniklas 
1262159047fSniklas void
input_file_open(char * filename,int pre)127*007c2a45Smiod input_file_open (char *filename, /* "" means use stdin. Must not be 0.  */
128*007c2a45Smiod 		 int pre)
1292159047fSniklas {
1302159047fSniklas   int c;
1312159047fSniklas   char buf[80];
1322159047fSniklas 
1332159047fSniklas   preprocess = pre;
1342159047fSniklas 
1352159047fSniklas   assert (filename != 0);	/* Filename may not be NULL.  */
1362159047fSniklas   if (filename[0])
137*007c2a45Smiod     {
138c074d1c9Sdrahn       f_in = fopen (filename, FOPEN_RT);
1392159047fSniklas       file_name = filename;
1402159047fSniklas     }
1412159047fSniklas   else
1422159047fSniklas     {
143*007c2a45Smiod       /* Use stdin for the input file.  */
144*007c2a45Smiod       f_in = stdin;
145*007c2a45Smiod       /* For error messages.  */
146*007c2a45Smiod       file_name = _("{standard input}");
147*007c2a45Smiod     }
148*007c2a45Smiod 
149*007c2a45Smiod   if (f_in)
150*007c2a45Smiod     c = getc (f_in);
151*007c2a45Smiod 
152*007c2a45Smiod   if (f_in == NULL || ferror (f_in))
153*007c2a45Smiod     {
154*007c2a45Smiod #ifdef BFD_ASSEMBLER
155*007c2a45Smiod       bfd_set_error (bfd_error_system_call);
156*007c2a45Smiod #endif
157*007c2a45Smiod       as_perror (_("Can't open %s for reading"), file_name);
158*007c2a45Smiod 
159*007c2a45Smiod       if (f_in)
160*007c2a45Smiod 	{
161*007c2a45Smiod 	  fclose (f_in);
162*007c2a45Smiod 	  f_in = NULL;
163*007c2a45Smiod 	}
1642159047fSniklas       return;
1652159047fSniklas     }
1662159047fSniklas 
1672159047fSniklas   if (c == '#')
168c074d1c9Sdrahn     {
169c074d1c9Sdrahn       /* Begins with comment, may not want to preprocess.  */
1702159047fSniklas       c = getc (f_in);
1712159047fSniklas       if (c == 'N')
1722159047fSniklas 	{
1732159047fSniklas 	  fgets (buf, 80, f_in);
174c074d1c9Sdrahn 	  if (!strncmp (buf, "O_APP", 5) && ISSPACE (buf[5]))
1752159047fSniklas 	    preprocess = 0;
1762159047fSniklas 	  if (!strchr (buf, '\n'))
177c074d1c9Sdrahn 	    ungetc ('#', f_in);	/* It was longer.  */
178c074d1c9Sdrahn 	  else
179c074d1c9Sdrahn 	    ungetc ('\n', f_in);
180c074d1c9Sdrahn 	}
181c074d1c9Sdrahn       else if (c == 'A')
182c074d1c9Sdrahn 	{
183c074d1c9Sdrahn 	  fgets (buf, 80, f_in);
184c074d1c9Sdrahn 	  if (!strncmp (buf, "PP", 2) && ISSPACE (buf[2]))
185c074d1c9Sdrahn 	    preprocess = 1;
186c074d1c9Sdrahn 	  if (!strchr (buf, '\n'))
187c074d1c9Sdrahn 	    ungetc ('#', f_in);
1882159047fSniklas 	  else
1892159047fSniklas 	    ungetc ('\n', f_in);
1902159047fSniklas 	}
1912159047fSniklas       else if (c == '\n')
1922159047fSniklas 	ungetc ('\n', f_in);
1932159047fSniklas       else
1942159047fSniklas 	ungetc ('#', f_in);
1952159047fSniklas     }
1962159047fSniklas   else
1972159047fSniklas     ungetc (c, f_in);
1982159047fSniklas }
1992159047fSniklas 
2002159047fSniklas /* Close input file.  */
201c074d1c9Sdrahn 
2022159047fSniklas void
input_file_close(void)203*007c2a45Smiod input_file_close (void)
2042159047fSniklas {
205c074d1c9Sdrahn   /* Don't close a null file pointer.  */
2062159047fSniklas   if (f_in != NULL)
2072159047fSniklas     fclose (f_in);
208c074d1c9Sdrahn 
2092159047fSniklas   f_in = 0;
210b55d4692Sfgsch }
2112159047fSniklas 
2122159047fSniklas /* This function is passed to do_scrub_chars.  */
2132159047fSniklas 
2142159047fSniklas static int
input_file_get(char * buf,int buflen)215*007c2a45Smiod input_file_get (char *buf, int buflen)
2162159047fSniklas {
2172159047fSniklas   int size;
2182159047fSniklas 
219f7cc78ecSespie   size = fread (buf, sizeof (char), buflen, f_in);
2202159047fSniklas   if (size < 0)
2212159047fSniklas     {
222*007c2a45Smiod #ifdef BFD_ASSEMBLER
223*007c2a45Smiod       bfd_set_error (bfd_error_system_call);
224*007c2a45Smiod #endif
225f7cc78ecSespie       as_perror (_("Can't read from %s"), file_name);
2262159047fSniklas       size = 0;
2272159047fSniklas     }
2282159047fSniklas   return size;
2292159047fSniklas }
2302159047fSniklas 
2312159047fSniklas /* Read a buffer from the input file.  */
2322159047fSniklas 
2332159047fSniklas char *
input_file_give_next_buffer(char * where)234*007c2a45Smiod input_file_give_next_buffer (char *where /* Where to place 1st character of new buffer.  */)
2352159047fSniklas {
2362159047fSniklas   char *return_value;		/* -> Last char of what we read, + 1.  */
2372159047fSniklas   register int size;
2382159047fSniklas 
2392159047fSniklas   if (f_in == (FILE *) 0)
2402159047fSniklas     return 0;
241c074d1c9Sdrahn   /* fflush (stdin); could be done here if you want to synchronise
242c074d1c9Sdrahn      stdin and stdout, for the case where our input file is stdin.
243c074d1c9Sdrahn      Since the assembler shouldn't do any output to stdout, we
244c074d1c9Sdrahn      don't bother to synch output and input.  */
2452159047fSniklas   if (preprocess)
2462159047fSniklas     size = do_scrub_chars (input_file_get, where, BUFFER_SIZE);
2472159047fSniklas   else
2482159047fSniklas     size = fread (where, sizeof (char), BUFFER_SIZE, f_in);
2492159047fSniklas   if (size < 0)
2502159047fSniklas     {
251*007c2a45Smiod #ifdef BFD_ASSEMBLER
252*007c2a45Smiod       bfd_set_error (bfd_error_system_call);
253*007c2a45Smiod #endif
254f7cc78ecSespie       as_perror (_("Can't read from %s"), file_name);
2552159047fSniklas       size = 0;
2562159047fSniklas     }
2572159047fSniklas   if (size)
2582159047fSniklas     return_value = where + size;
2592159047fSniklas   else
2602159047fSniklas     {
2612159047fSniklas       if (fclose (f_in))
262*007c2a45Smiod 	{
263*007c2a45Smiod #ifdef BFD_ASSEMBLER
264*007c2a45Smiod 	  bfd_set_error (bfd_error_system_call);
265*007c2a45Smiod #endif
266f7cc78ecSespie 	  as_perror (_("Can't close %s"), file_name);
267*007c2a45Smiod 	}
2682159047fSniklas       f_in = (FILE *) 0;
2692159047fSniklas       return_value = 0;
2702159047fSniklas     }
271c074d1c9Sdrahn 
272c074d1c9Sdrahn   return return_value;
2732159047fSniklas }
274