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 35 static 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 */ 40 int 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 56 static FILE *f_in; 57 static char *file_name; 58 59 /* Struct for saving the state of this module for file includes. */ 60 struct 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 70 void 71 input_file_begin () 72 { 73 f_in = (FILE *) 0; 74 } 75 76 void 77 input_file_end () 78 { 79 } 80 81 /* Return BUFFER_SIZE. */ 82 unsigned int 83 input_file_buffer_size () 84 { 85 return (BUFFER_SIZE); 86 } 87 88 int 89 input_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 (). */ 96 char * 97 input_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 114 void 115 input_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 131 void 132 input_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. */ 183 void 184 input_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 195 static int 196 input_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 213 char * 214 input_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