input-file.c revision 33965
1/* input_file.c - Deal with Input Files - 2 Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc. 3 4 This file is part of GAS, the GNU Assembler. 5 6 GAS is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GAS is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GAS; see the file COPYING. If not, write to 18 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19 20/* 21 * Confines all details of reading source bytes to this module. 22 * All O/S specific crocks should live here. 23 * What we lose in "efficiency" we gain in modularity. 24 * Note we don't need to #include the "as.h" file. No common coupling! 25 */ 26 27#include <stdio.h> 28#include <string.h> 29 30#include "as.h" 31#include "input-file.h" 32 33static int input_file_get PARAMS ((char **)); 34 35/* This variable is non-zero if the file currently being read should be 36 preprocessed by app. It is zero if the file can be read straight in. 37 */ 38int preprocess = 0; 39 40/* 41 * This code opens a file, then delivers BUFFER_SIZE character 42 * chunks of the file on demand. 43 * BUFFER_SIZE is supposed to be a number chosen for speed. 44 * The caller only asks once what BUFFER_SIZE is, and asks before 45 * the nature of the input files (if any) is known. 46 */ 47 48#define BUFFER_SIZE (32 * 1024) 49 50/* 51 * We use static data: the data area is not sharable. 52 */ 53 54static FILE *f_in; 55static char *file_name; 56 57/* Struct for saving the state of this module for file includes. */ 58struct saved_file 59 { 60 FILE *f_in; 61 char *file_name; 62 int preprocess; 63 char *app_save; 64 }; 65 66/* These hooks accomodate most operating systems. */ 67 68void 69input_file_begin () 70{ 71 f_in = (FILE *) 0; 72} 73 74void 75input_file_end () 76{ 77} 78 79/* Return BUFFER_SIZE. */ 80unsigned int 81input_file_buffer_size () 82{ 83 return (BUFFER_SIZE); 84} 85 86int 87input_file_is_open () 88{ 89 return f_in != (FILE *) 0; 90} 91 92/* Push the state of our input, returning a pointer to saved info that 93 can be restored with input_file_pop (). */ 94char * 95input_file_push () 96{ 97 register struct saved_file *saved; 98 99 saved = (struct saved_file *) xmalloc (sizeof *saved); 100 101 saved->f_in = f_in; 102 saved->file_name = file_name; 103 saved->preprocess = preprocess; 104 if (preprocess) 105 saved->app_save = app_push (); 106 107 input_file_begin (); /* Initialize for new file */ 108 109 return (char *) saved; 110} 111 112void 113input_file_pop (arg) 114 char *arg; 115{ 116 register struct saved_file *saved = (struct saved_file *) arg; 117 118 input_file_end (); /* Close out old file */ 119 120 f_in = saved->f_in; 121 file_name = saved->file_name; 122 preprocess = saved->preprocess; 123 if (preprocess) 124 app_pop (saved->app_save); 125 126 free (arg); 127} 128 129void 130input_file_open (filename, pre) 131 char *filename; /* "" means use stdin. Must not be 0. */ 132 int pre; 133{ 134 int c; 135 char buf[80]; 136 137 preprocess = pre; 138 139 assert (filename != 0); /* Filename may not be NULL. */ 140 if (filename[0]) 141 { /* We have a file name. Suck it and see. */ 142 f_in = fopen (filename, "r"); 143 file_name = filename; 144 } 145 else 146 { /* use stdin for the input file. */ 147 f_in = stdin; 148 file_name = "{standard input}"; /* For error messages. */ 149 } 150 if (f_in == (FILE *) 0) 151 { 152 as_bad ("Can't open %s for reading.", file_name); 153 as_perror ("%s", file_name); 154 return; 155 } 156 157 c = getc (f_in); 158 if (c == '#') 159 { /* Begins with comment, may not want to preprocess */ 160 c = getc (f_in); 161 if (c == 'N') 162 { 163 fgets (buf, 80, f_in); 164 if (!strcmp (buf, "O_APP\n")) 165 preprocess = 0; 166 if (!strchr (buf, '\n')) 167 ungetc ('#', f_in); /* It was longer */ 168 else 169 ungetc ('\n', f_in); 170 } 171 else if (c == '\n') 172 ungetc ('\n', f_in); 173 else 174 ungetc ('#', f_in); 175 } 176 else 177 ungetc (c, f_in); 178} 179 180/* Close input file. */ 181void 182input_file_close () 183{ 184 if (f_in != NULL) 185 { 186 fclose (f_in); 187 } /* don't close a null file pointer */ 188 f_in = 0; 189} /* input_file_close() */ 190 191/* This function is passed to do_scrub_chars. */ 192 193static int 194input_file_get (from) 195 char **from; 196{ 197 static char buf[BUFFER_SIZE]; 198 int size; 199 200 size = fread (buf, sizeof (char), sizeof buf, f_in); 201 if (size < 0) 202 { 203 as_perror ("Can't read from %s", file_name); 204 size = 0; 205 } 206 *from = buf; 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 248/* end of input-file.c */ 249