xref: /openbsd-src/gnu/usr.bin/binutils-2.17/gas/input-file.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* input_file.c - Deal with Input Files -
2*3d8817e4Smiod    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001,
3*3d8817e4Smiod    2002, 2003, 2005
4*3d8817e4Smiod    Free Software Foundation, Inc.
5*3d8817e4Smiod 
6*3d8817e4Smiod    This file is part of GAS, the GNU Assembler.
7*3d8817e4Smiod 
8*3d8817e4Smiod    GAS is free software; you can redistribute it and/or modify
9*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
10*3d8817e4Smiod    the Free Software Foundation; either version 2, or (at your option)
11*3d8817e4Smiod    any later version.
12*3d8817e4Smiod 
13*3d8817e4Smiod    GAS is distributed in the hope that it will be useful,
14*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*3d8817e4Smiod    GNU General Public License for more details.
17*3d8817e4Smiod 
18*3d8817e4Smiod    You should have received a copy of the GNU General Public License
19*3d8817e4Smiod    along with GAS; see the file COPYING.  If not, write to the Free
20*3d8817e4Smiod    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21*3d8817e4Smiod    02110-1301, USA.  */
22*3d8817e4Smiod 
23*3d8817e4Smiod /* Confines all details of reading source bytes to this module.
24*3d8817e4Smiod    All O/S specific crocks should live here.
25*3d8817e4Smiod    What we lose in "efficiency" we gain in modularity.
26*3d8817e4Smiod    Note we don't need to #include the "as.h" file. No common coupling!  */
27*3d8817e4Smiod 
28*3d8817e4Smiod #include <stdio.h>
29*3d8817e4Smiod #include <string.h>
30*3d8817e4Smiod #include <errno.h>
31*3d8817e4Smiod #include "as.h"
32*3d8817e4Smiod #include "input-file.h"
33*3d8817e4Smiod #include "safe-ctype.h"
34*3d8817e4Smiod 
35*3d8817e4Smiod static int input_file_get (char *, int);
36*3d8817e4Smiod 
37*3d8817e4Smiod /* This variable is non-zero if the file currently being read should be
38*3d8817e4Smiod    preprocessed by app.  It is zero if the file can be read straight in.  */
39*3d8817e4Smiod int preprocess = 0;
40*3d8817e4Smiod 
41*3d8817e4Smiod /* This code opens a file, then delivers BUFFER_SIZE character
42*3d8817e4Smiod    chunks of the file on demand.
43*3d8817e4Smiod    BUFFER_SIZE is supposed to be a number chosen for speed.
44*3d8817e4Smiod    The caller only asks once what BUFFER_SIZE is, and asks before
45*3d8817e4Smiod    the nature of the input files (if any) is known.  */
46*3d8817e4Smiod 
47*3d8817e4Smiod #define BUFFER_SIZE (32 * 1024)
48*3d8817e4Smiod 
49*3d8817e4Smiod /* We use static data: the data area is not sharable.  */
50*3d8817e4Smiod 
51*3d8817e4Smiod static FILE *f_in;
52*3d8817e4Smiod static char *file_name;
53*3d8817e4Smiod 
54*3d8817e4Smiod /* Struct for saving the state of this module for file includes.  */
55*3d8817e4Smiod struct saved_file
56*3d8817e4Smiod   {
57*3d8817e4Smiod     FILE * f_in;
58*3d8817e4Smiod     char * file_name;
59*3d8817e4Smiod     int    preprocess;
60*3d8817e4Smiod     char * app_save;
61*3d8817e4Smiod   };
62*3d8817e4Smiod 
63*3d8817e4Smiod /* These hooks accommodate most operating systems.  */
64*3d8817e4Smiod 
65*3d8817e4Smiod void
input_file_begin(void)66*3d8817e4Smiod input_file_begin (void)
67*3d8817e4Smiod {
68*3d8817e4Smiod   f_in = (FILE *) 0;
69*3d8817e4Smiod }
70*3d8817e4Smiod 
71*3d8817e4Smiod void
input_file_end(void)72*3d8817e4Smiod input_file_end (void)
73*3d8817e4Smiod {
74*3d8817e4Smiod }
75*3d8817e4Smiod 
76*3d8817e4Smiod /* Return BUFFER_SIZE.  */
77*3d8817e4Smiod unsigned int
input_file_buffer_size(void)78*3d8817e4Smiod input_file_buffer_size (void)
79*3d8817e4Smiod {
80*3d8817e4Smiod   return (BUFFER_SIZE);
81*3d8817e4Smiod }
82*3d8817e4Smiod 
83*3d8817e4Smiod /* Push the state of our input, returning a pointer to saved info that
84*3d8817e4Smiod    can be restored with input_file_pop ().  */
85*3d8817e4Smiod 
86*3d8817e4Smiod char *
input_file_push(void)87*3d8817e4Smiod input_file_push (void)
88*3d8817e4Smiod {
89*3d8817e4Smiod   register struct saved_file *saved;
90*3d8817e4Smiod 
91*3d8817e4Smiod   saved = (struct saved_file *) xmalloc (sizeof *saved);
92*3d8817e4Smiod 
93*3d8817e4Smiod   saved->f_in = f_in;
94*3d8817e4Smiod   saved->file_name = file_name;
95*3d8817e4Smiod   saved->preprocess = preprocess;
96*3d8817e4Smiod   if (preprocess)
97*3d8817e4Smiod     saved->app_save = app_push ();
98*3d8817e4Smiod 
99*3d8817e4Smiod   /* Initialize for new file.  */
100*3d8817e4Smiod   input_file_begin ();
101*3d8817e4Smiod 
102*3d8817e4Smiod   return (char *) saved;
103*3d8817e4Smiod }
104*3d8817e4Smiod 
105*3d8817e4Smiod void
input_file_pop(char * arg)106*3d8817e4Smiod input_file_pop (char *arg)
107*3d8817e4Smiod {
108*3d8817e4Smiod   register struct saved_file *saved = (struct saved_file *) arg;
109*3d8817e4Smiod 
110*3d8817e4Smiod   input_file_end ();		/* Close out old file.  */
111*3d8817e4Smiod 
112*3d8817e4Smiod   f_in = saved->f_in;
113*3d8817e4Smiod   file_name = saved->file_name;
114*3d8817e4Smiod   preprocess = saved->preprocess;
115*3d8817e4Smiod   if (preprocess)
116*3d8817e4Smiod     app_pop (saved->app_save);
117*3d8817e4Smiod 
118*3d8817e4Smiod   free (arg);
119*3d8817e4Smiod }
120*3d8817e4Smiod 
121*3d8817e4Smiod void
input_file_open(char * filename,int pre)122*3d8817e4Smiod input_file_open (char *filename, /* "" means use stdin. Must not be 0.  */
123*3d8817e4Smiod 		 int pre)
124*3d8817e4Smiod {
125*3d8817e4Smiod   int c;
126*3d8817e4Smiod   char buf[80];
127*3d8817e4Smiod 
128*3d8817e4Smiod   preprocess = pre;
129*3d8817e4Smiod 
130*3d8817e4Smiod   assert (filename != 0);	/* Filename may not be NULL.  */
131*3d8817e4Smiod   if (filename[0])
132*3d8817e4Smiod     {
133*3d8817e4Smiod       f_in = fopen (filename, FOPEN_RT);
134*3d8817e4Smiod       file_name = filename;
135*3d8817e4Smiod     }
136*3d8817e4Smiod   else
137*3d8817e4Smiod     {
138*3d8817e4Smiod       /* Use stdin for the input file.  */
139*3d8817e4Smiod       f_in = stdin;
140*3d8817e4Smiod       /* For error messages.  */
141*3d8817e4Smiod       file_name = _("{standard input}");
142*3d8817e4Smiod     }
143*3d8817e4Smiod 
144*3d8817e4Smiod   if (f_in == NULL)
145*3d8817e4Smiod     {
146*3d8817e4Smiod       bfd_set_error (bfd_error_system_call);
147*3d8817e4Smiod       as_perror (_("Can't open %s for reading"), file_name);
148*3d8817e4Smiod       return;
149*3d8817e4Smiod     }
150*3d8817e4Smiod 
151*3d8817e4Smiod   c = getc (f_in);
152*3d8817e4Smiod 
153*3d8817e4Smiod   if (ferror (f_in))
154*3d8817e4Smiod     {
155*3d8817e4Smiod       bfd_set_error (bfd_error_system_call);
156*3d8817e4Smiod       as_perror (_("Can't open %s for reading"), file_name);
157*3d8817e4Smiod 
158*3d8817e4Smiod       fclose (f_in);
159*3d8817e4Smiod       f_in = NULL;
160*3d8817e4Smiod       return;
161*3d8817e4Smiod     }
162*3d8817e4Smiod 
163*3d8817e4Smiod   if (c == '#')
164*3d8817e4Smiod     {
165*3d8817e4Smiod       /* Begins with comment, may not want to preprocess.  */
166*3d8817e4Smiod       c = getc (f_in);
167*3d8817e4Smiod       if (c == 'N')
168*3d8817e4Smiod 	{
169*3d8817e4Smiod 	  fgets (buf, 80, f_in);
170*3d8817e4Smiod 	  if (!strncmp (buf, "O_APP", 5) && ISSPACE (buf[5]))
171*3d8817e4Smiod 	    preprocess = 0;
172*3d8817e4Smiod 	  if (!strchr (buf, '\n'))
173*3d8817e4Smiod 	    ungetc ('#', f_in);	/* It was longer.  */
174*3d8817e4Smiod 	  else
175*3d8817e4Smiod 	    ungetc ('\n', f_in);
176*3d8817e4Smiod 	}
177*3d8817e4Smiod       else if (c == 'A')
178*3d8817e4Smiod 	{
179*3d8817e4Smiod 	  fgets (buf, 80, f_in);
180*3d8817e4Smiod 	  if (!strncmp (buf, "PP", 2) && ISSPACE (buf[2]))
181*3d8817e4Smiod 	    preprocess = 1;
182*3d8817e4Smiod 	  if (!strchr (buf, '\n'))
183*3d8817e4Smiod 	    ungetc ('#', f_in);
184*3d8817e4Smiod 	  else
185*3d8817e4Smiod 	    ungetc ('\n', f_in);
186*3d8817e4Smiod 	}
187*3d8817e4Smiod       else if (c == '\n')
188*3d8817e4Smiod 	ungetc ('\n', f_in);
189*3d8817e4Smiod       else
190*3d8817e4Smiod 	ungetc ('#', f_in);
191*3d8817e4Smiod     }
192*3d8817e4Smiod   else
193*3d8817e4Smiod     ungetc (c, f_in);
194*3d8817e4Smiod }
195*3d8817e4Smiod 
196*3d8817e4Smiod /* Close input file.  */
197*3d8817e4Smiod 
198*3d8817e4Smiod void
input_file_close(void)199*3d8817e4Smiod input_file_close (void)
200*3d8817e4Smiod {
201*3d8817e4Smiod   /* Don't close a null file pointer.  */
202*3d8817e4Smiod   if (f_in != NULL)
203*3d8817e4Smiod     fclose (f_in);
204*3d8817e4Smiod 
205*3d8817e4Smiod   f_in = 0;
206*3d8817e4Smiod }
207*3d8817e4Smiod 
208*3d8817e4Smiod /* This function is passed to do_scrub_chars.  */
209*3d8817e4Smiod 
210*3d8817e4Smiod static int
input_file_get(char * buf,int buflen)211*3d8817e4Smiod input_file_get (char *buf, int buflen)
212*3d8817e4Smiod {
213*3d8817e4Smiod   int size;
214*3d8817e4Smiod 
215*3d8817e4Smiod   size = fread (buf, sizeof (char), buflen, f_in);
216*3d8817e4Smiod   if (size < 0)
217*3d8817e4Smiod     {
218*3d8817e4Smiod       bfd_set_error (bfd_error_system_call);
219*3d8817e4Smiod       as_perror (_("Can't read from %s"), file_name);
220*3d8817e4Smiod       size = 0;
221*3d8817e4Smiod     }
222*3d8817e4Smiod   return size;
223*3d8817e4Smiod }
224*3d8817e4Smiod 
225*3d8817e4Smiod /* Read a buffer from the input file.  */
226*3d8817e4Smiod 
227*3d8817e4Smiod char *
input_file_give_next_buffer(char * where)228*3d8817e4Smiod input_file_give_next_buffer (char *where /* Where to place 1st character of new buffer.  */)
229*3d8817e4Smiod {
230*3d8817e4Smiod   char *return_value;		/* -> Last char of what we read, + 1.  */
231*3d8817e4Smiod   register int size;
232*3d8817e4Smiod 
233*3d8817e4Smiod   if (f_in == (FILE *) 0)
234*3d8817e4Smiod     return 0;
235*3d8817e4Smiod   /* fflush (stdin); could be done here if you want to synchronise
236*3d8817e4Smiod      stdin and stdout, for the case where our input file is stdin.
237*3d8817e4Smiod      Since the assembler shouldn't do any output to stdout, we
238*3d8817e4Smiod      don't bother to synch output and input.  */
239*3d8817e4Smiod   if (preprocess)
240*3d8817e4Smiod     size = do_scrub_chars (input_file_get, where, BUFFER_SIZE);
241*3d8817e4Smiod   else
242*3d8817e4Smiod     size = fread (where, sizeof (char), BUFFER_SIZE, f_in);
243*3d8817e4Smiod   if (size < 0)
244*3d8817e4Smiod     {
245*3d8817e4Smiod       bfd_set_error (bfd_error_system_call);
246*3d8817e4Smiod       as_perror (_("Can't read from %s"), file_name);
247*3d8817e4Smiod       size = 0;
248*3d8817e4Smiod     }
249*3d8817e4Smiod   if (size)
250*3d8817e4Smiod     return_value = where + size;
251*3d8817e4Smiod   else
252*3d8817e4Smiod     {
253*3d8817e4Smiod       if (fclose (f_in))
254*3d8817e4Smiod 	{
255*3d8817e4Smiod 	  bfd_set_error (bfd_error_system_call);
256*3d8817e4Smiod 	  as_perror (_("Can't close %s"), file_name);
257*3d8817e4Smiod 	}
258*3d8817e4Smiod       f_in = (FILE *) 0;
259*3d8817e4Smiod       return_value = 0;
260*3d8817e4Smiod     }
261*3d8817e4Smiod 
262*3d8817e4Smiod   return return_value;
263*3d8817e4Smiod }
264