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