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