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