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