input-file.c revision 77298
1/* input_file.c - Deal with Input Files - 2 Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 98, 99, 2000 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/* 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 29#include <stdio.h> 30#include <string.h> 31 32#include "as.h" 33#include "input-file.h" 34 35static int input_file_get PARAMS ((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 */ 40int preprocess = 0; 41 42/* 43 * This code opens a file, then delivers BUFFER_SIZE character 44 * chunks of the file on demand. 45 * BUFFER_SIZE is supposed to be a number chosen for speed. 46 * The caller only asks once what BUFFER_SIZE is, and asks before 47 * the nature of the input files (if any) is known. 48 */ 49 50#define BUFFER_SIZE (32 * 1024) 51 52/* 53 * We use static data: the data area is not sharable. 54 */ 55 56static FILE *f_in; 57static char *file_name; 58 59/* Struct for saving the state of this module for file includes. */ 60struct saved_file { 61 FILE *f_in; 62 char *file_name; 63 int preprocess; 64 char *app_save; 65}; 66 67/* These hooks accomodate most operating systems. */ 68 69void 70input_file_begin () 71{ 72 f_in = (FILE *) 0; 73} 74 75void 76input_file_end () 77{ 78} 79 80/* Return BUFFER_SIZE. */ 81unsigned int 82input_file_buffer_size () 83{ 84 return (BUFFER_SIZE); 85} 86 87int 88input_file_is_open () 89{ 90 return f_in != (FILE *) 0; 91} 92 93/* Push the state of our input, returning a pointer to saved info that 94 can be restored with input_file_pop (). */ 95char * 96input_file_push () 97{ 98 register struct saved_file *saved; 99 100 saved = (struct saved_file *) xmalloc (sizeof *saved); 101 102 saved->f_in = f_in; 103 saved->file_name = file_name; 104 saved->preprocess = preprocess; 105 if (preprocess) 106 saved->app_save = app_push (); 107 108 input_file_begin (); /* Initialize for new file */ 109 110 return (char *) saved; 111} 112 113void 114input_file_pop (arg) 115 char *arg; 116{ 117 register struct saved_file *saved = (struct saved_file *) arg; 118 119 input_file_end (); /* Close out old file */ 120 121 f_in = saved->f_in; 122 file_name = saved->file_name; 123 preprocess = saved->preprocess; 124 if (preprocess) 125 app_pop (saved->app_save); 126 127 free (arg); 128} 129 130void 131input_file_open (filename, pre) 132 char *filename; /* "" means use stdin. Must not be 0. */ 133 int pre; 134{ 135 int c; 136 char buf[80]; 137 138 preprocess = pre; 139 140 assert (filename != 0); /* Filename may not be NULL. */ 141 if (filename[0]) 142 { /* We have a file name. Suck it and see. */ 143 f_in = fopen (filename, "r"); 144 file_name = filename; 145 } 146 else 147 { /* use stdin for the input file. */ 148 f_in = stdin; 149 file_name = _("{standard input}"); /* For error messages. */ 150 } 151 if (f_in == (FILE *) 0) 152 { 153 as_bad (_("Can't open %s for reading."), file_name); 154 as_perror ("%s", file_name); 155 return; 156 } 157 158 c = getc (f_in); 159 if (c == '#') 160 { /* Begins with comment, may not want to preprocess */ 161 c = getc (f_in); 162 if (c == 'N') 163 { 164 fgets (buf, 80, f_in); 165 if (!strcmp (buf, "O_APP\n")) 166 preprocess = 0; 167 if (!strchr (buf, '\n')) 168 ungetc ('#', f_in); /* It was longer */ 169 else 170 ungetc ('\n', f_in); 171 } 172 else if (c == '\n') 173 ungetc ('\n', f_in); 174 else 175 ungetc ('#', f_in); 176 } 177 else 178 ungetc (c, f_in); 179} 180 181/* Close input file. */ 182void 183input_file_close () 184{ 185 if (f_in != NULL) 186 { 187 fclose (f_in); 188 } /* don't close a null file pointer */ 189 f_in = 0; 190} 191 192/* This function is passed to do_scrub_chars. */ 193 194static int 195input_file_get (buf, buflen) 196 char *buf; 197 int buflen; 198{ 199 int size; 200 201 size = fread (buf, sizeof (char), buflen, f_in); 202 if (size < 0) 203 { 204 as_perror (_("Can't read from %s"), file_name); 205 size = 0; 206 } 207 return size; 208} 209 210/* Read a buffer from the input file. */ 211 212char * 213input_file_give_next_buffer (where) 214 char *where; /* Where to place 1st character of new buffer. */ 215{ 216 char *return_value; /* -> Last char of what we read, + 1. */ 217 register int size; 218 219 if (f_in == (FILE *) 0) 220 return 0; 221 /* 222 * fflush (stdin); could be done here if you want to synchronise 223 * stdin and stdout, for the case where our input file is stdin. 224 * Since the assembler shouldn't do any output to stdout, we 225 * don't bother to synch output and input. 226 */ 227 if (preprocess) 228 size = do_scrub_chars (input_file_get, where, BUFFER_SIZE); 229 else 230 size = fread (where, sizeof (char), BUFFER_SIZE, f_in); 231 if (size < 0) 232 { 233 as_perror (_("Can't read from %s"), file_name); 234 size = 0; 235 } 236 if (size) 237 return_value = where + size; 238 else 239 { 240 if (fclose (f_in)) 241 as_perror (_("Can't close %s"), file_name); 242 f_in = (FILE *) 0; 243 return_value = 0; 244 } 245 return (return_value); 246} 247