1 1.1 christos /* input_file.c - Deal with Input Files - 2 1.10 christos Copyright (C) 1987-2025 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This file is part of GAS, the GNU Assembler. 5 1.1 christos 6 1.1 christos GAS is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 3, or (at your option) 9 1.1 christos any later version. 10 1.1 christos 11 1.1 christos GAS is distributed in the hope that it will be useful, 12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 christos GNU General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with GAS; see the file COPYING. If not, write to the Free 18 1.1 christos Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 19 1.1 christos 02110-1301, USA. */ 20 1.1 christos 21 1.1 christos /* Confines all details of reading source bytes to this module. 22 1.1 christos All O/S specific crocks should live here. 23 1.1 christos What we lose in "efficiency" we gain in modularity. 24 1.1 christos Note we don't need to #include the "as.h" file. No common coupling! */ 25 1.1 christos 26 1.1 christos #include "as.h" 27 1.1 christos #include "input-file.h" 28 1.1 christos #include "safe-ctype.h" 29 1.1 christos 30 1.1 christos /* This variable is non-zero if the file currently being read should be 31 1.1 christos preprocessed by app. It is zero if the file can be read straight in. */ 32 1.1 christos int preprocess = 0; 33 1.1 christos 34 1.1 christos /* This code opens a file, then delivers BUFFER_SIZE character 35 1.1 christos chunks of the file on demand. 36 1.1 christos BUFFER_SIZE is supposed to be a number chosen for speed. 37 1.1 christos The caller only asks once what BUFFER_SIZE is, and asks before 38 1.1 christos the nature of the input files (if any) is known. */ 39 1.1 christos 40 1.1 christos #define BUFFER_SIZE (32 * 1024) 41 1.1 christos 42 1.1 christos /* We use static data: the data area is not sharable. */ 43 1.1 christos 44 1.1 christos static FILE *f_in; 45 1.5 christos static const char *file_name; 46 1.1 christos 47 1.1 christos /* Struct for saving the state of this module for file includes. */ 48 1.1 christos struct saved_file 49 1.1 christos { 50 1.1 christos FILE * f_in; 51 1.5 christos const char * file_name; 52 1.1 christos int preprocess; 53 1.1 christos char * app_save; 54 1.1 christos }; 55 1.1 christos 56 1.1 christos /* These hooks accommodate most operating systems. */ 58 1.1 christos 59 1.1 christos void 60 1.1 christos input_file_begin (void) 61 1.10 christos { 62 1.1 christos f_in = NULL; 63 1.1 christos } 64 1.1 christos 65 1.1 christos void 66 1.1 christos input_file_end (void) 67 1.1 christos { 68 1.1 christos } 69 1.1 christos 70 1.1 christos /* Return BUFFER_SIZE. */ 71 1.1 christos size_t 72 1.1 christos input_file_buffer_size (void) 73 1.1 christos { 74 1.1 christos return (BUFFER_SIZE); 75 1.1 christos } 76 1.1 christos 77 1.1 christos /* Push the state of our input, returning a pointer to saved info that 78 1.1 christos can be restored with input_file_pop (). */ 79 1.1 christos 80 1.1 christos char * 81 1.1 christos input_file_push (void) 82 1.3 christos { 83 1.1 christos struct saved_file *saved; 84 1.5 christos 85 1.1 christos saved = XNEW (struct saved_file); 86 1.1 christos 87 1.1 christos saved->f_in = f_in; 88 1.1 christos saved->file_name = file_name; 89 1.1 christos saved->preprocess = preprocess; 90 1.1 christos if (preprocess) 91 1.1 christos saved->app_save = app_push (); 92 1.1 christos 93 1.1 christos /* Initialize for new file. */ 94 1.1 christos input_file_begin (); 95 1.1 christos 96 1.1 christos return (char *) saved; 97 1.1 christos } 98 1.1 christos 99 1.1 christos void 100 1.1 christos input_file_pop (char *arg) 101 1.3 christos { 102 1.1 christos struct saved_file *saved = (struct saved_file *) arg; 103 1.1 christos 104 1.1 christos input_file_end (); /* Close out old file. */ 105 1.1 christos 106 1.1 christos f_in = saved->f_in; 107 1.1 christos file_name = saved->file_name; 108 1.1 christos preprocess = saved->preprocess; 109 1.1 christos if (preprocess) 110 1.1 christos app_pop (saved->app_save); 111 1.1 christos 112 1.1 christos free (arg); 113 1.1 christos } 114 1.5 christos 115 1.5 christos /* Open the specified file, "" means stdin. Filename must not be null. */ 117 1.5 christos 118 1.1 christos void 119 1.1 christos input_file_open (const char *filename, 120 1.1 christos int pre) 121 1.1 christos { 122 1.1 christos int c; 123 1.1 christos char buf[80]; 124 1.1 christos 125 1.1 christos preprocess = pre; 126 1.1 christos 127 1.1 christos gas_assert (filename != 0); /* Filename may not be NULL. */ 128 1.1 christos if (filename[0]) 129 1.1 christos { 130 1.1 christos f_in = fopen (filename, FOPEN_RT); 131 1.1 christos file_name = filename; 132 1.1 christos } 133 1.1 christos else 134 1.1 christos { 135 1.1 christos /* Use stdin for the input file. */ 136 1.1 christos f_in = stdin; 137 1.1 christos /* For error messages. */ 138 1.1 christos file_name = _("{standard input}"); 139 1.1 christos } 140 1.1 christos 141 1.1 christos if (f_in == NULL) 142 1.1 christos { 143 1.1 christos as_bad (_("can't open %s for reading: %s"), 144 1.1 christos file_name, xstrerror (errno)); 145 1.1 christos return; 146 1.1 christos } 147 1.1 christos 148 1.1 christos c = getc (f_in); 149 1.1 christos 150 1.1 christos if (ferror (f_in)) 151 1.1 christos { 152 1.1 christos as_bad (_("can't read from %s: %s"), 153 1.1 christos file_name, xstrerror (errno)); 154 1.1 christos 155 1.1 christos fclose (f_in); 156 1.1 christos f_in = NULL; 157 1.1 christos return; 158 1.1 christos } 159 1.1 christos 160 1.1 christos /* Check for an empty input file. */ 161 1.1 christos if (feof (f_in)) 162 1.1 christos { 163 1.1 christos fclose (f_in); 164 1.1 christos f_in = NULL; 165 1.1 christos return; 166 1.1 christos } 167 1.10 christos gas_assert (c != EOF); 168 1.10 christos 169 1.10 christos if (strchr (line_comment_chars, '#') 170 1.1 christos ? c == '#' 171 1.1 christos : c && strchr (line_comment_chars, c)) 172 1.10 christos { 173 1.10 christos /* Begins with comment, may not want to preprocess. */ 174 1.1 christos int lead = c; 175 1.1 christos 176 1.1 christos c = getc (f_in); 177 1.8 christos if (c == 'N') 178 1.10 christos { 179 1.1 christos char *p = fgets (buf, sizeof (buf), f_in); 180 1.8 christos if (p && startswith (p, "O_APP") && is_end_of_line (p[5])) 181 1.10 christos preprocess = 0; 182 1.1 christos if (!p || !strchr (p, '\n')) 183 1.1 christos ungetc (lead, f_in); 184 1.1 christos else 185 1.1 christos ungetc ('\n', f_in); 186 1.1 christos } 187 1.8 christos else if (c == 'A') 188 1.10 christos { 189 1.1 christos char *p = fgets (buf, sizeof (buf), f_in); 190 1.8 christos if (p && startswith (p, "PP") && is_end_of_line (p[2])) 191 1.10 christos preprocess = 1; 192 1.1 christos if (!p || !strchr (p, '\n')) 193 1.1 christos ungetc (lead, f_in); 194 1.1 christos else 195 1.1 christos ungetc ('\n', f_in); 196 1.1 christos } 197 1.1 christos else if (c == '\n') 198 1.10 christos ungetc ('\n', f_in); 199 1.1 christos else 200 1.1 christos ungetc (lead, f_in); 201 1.1 christos } 202 1.1 christos else 203 1.1 christos ungetc (c, f_in); 204 1.1 christos } 205 1.1 christos 206 1.1 christos /* Close input file. */ 207 1.1 christos 208 1.1 christos void 209 1.1 christos input_file_close (void) 210 1.1 christos { 211 1.1 christos /* Don't close a null file pointer. */ 212 1.1 christos if (f_in != NULL) 213 1.1 christos fclose (f_in); 214 1.1 christos 215 1.1 christos f_in = 0; 216 1.1 christos } 217 1.1 christos 218 1.1 christos /* This function is passed to do_scrub_chars. */ 219 1.1 christos 220 1.1 christos static size_t 221 1.1 christos input_file_get (char *buf, size_t buflen) 222 1.1 christos { 223 1.1 christos size_t size; 224 1.1 christos 225 1.3 christos if (feof (f_in)) 226 1.1 christos return 0; 227 1.1 christos 228 1.1 christos size = fread (buf, sizeof (char), buflen, f_in); 229 1.1 christos if (ferror (f_in)) 230 1.1 christos as_bad (_("can't read from %s: %s"), file_name, xstrerror (errno)); 231 1.1 christos return size; 232 1.1 christos } 233 1.1 christos 234 1.1 christos /* Read a buffer from the input file. */ 235 1.1 christos 236 1.1 christos char * 237 1.1 christos input_file_give_next_buffer (char *where /* Where to place 1st character of new buffer. */) 238 1.1 christos { 239 1.1 christos char *return_value; /* -> Last char of what we read, + 1. */ 240 1.10 christos size_t size; 241 1.1 christos 242 1.1 christos if (f_in == NULL) 243 1.1 christos return 0; 244 1.1 christos /* fflush (stdin); could be done here if you want to synchronise 245 1.1 christos stdin and stdout, for the case where our input file is stdin. 246 1.1 christos Since the assembler shouldn't do any output to stdout, we 247 1.10 christos don't bother to synch output and input. */ 248 1.10 christos if (preprocess) 249 1.1 christos size = do_scrub_chars (input_file_get, where, BUFFER_SIZE, 250 1.10 christos multibyte_handling == multibyte_warn); 251 1.10 christos else 252 1.10 christos { 253 1.10 christos size = input_file_get (where, BUFFER_SIZE); 254 1.10 christos 255 1.10 christos if (multibyte_handling == multibyte_warn) 256 1.10 christos { 257 1.10 christos const unsigned char *start = (const unsigned char *) where; 258 1.10 christos 259 1.10 christos (void) scan_for_multibyte_characters (start, start + size, 260 1.10 christos true /* Generate warnings */); 261 1.1 christos } 262 1.1 christos } 263 1.1 christos 264 1.1 christos if (size) 265 1.1 christos return_value = where + size; 266 1.1 christos else 267 1.1 christos { 268 1.1 christos if (fclose (f_in)) 269 1.10 christos as_warn (_("can't close %s: %s"), file_name, xstrerror (errno)); 270 1.1 christos 271 1.1 christos f_in = NULL; 272 1.1 christos return_value = 0; 273 1.1 christos } 274 1.1 christos 275 return return_value; 276 } 277