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