1/* input_file.c - Deal with Input Files - 2 Copyright (C) 1987 Free Software Foundation, Inc. 3 4This file is part of GAS, the GNU Assembler. 5 6GAS is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 1, or (at your option) 9any later version. 10 11GAS is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with GAS; see the file COPYING. If not, write to 18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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#define NDEBUG /* JF remove asserts */ 28 29#include <stdio.h> 30#include <stdlib.h> 31#include <string.h> 32#include <assert.h> 33#include <libc.h> 34#include "input-file.h" 35#include "xmalloc.h" 36#include "input-scrub.h" 37#include "app.h" 38#include "as.h" 39 40/* 41 * This variable is non-zero if the file currently being read should be 42 * preprocessed by app. It is zero if the file can be read straight in. 43 */ 44#ifndef SUSPECT 45static 46#endif 47int preprocess = 0; 48 49/* 50 * This code opens a file, then delivers BUFFER_SIZE character 51 * chunks of the file on demand. 52 * BUFFER_SIZE is supposed to be a number chosen for speed. 53 * The caller only asks once what BUFFER_SIZE is, and asks before 54 * the nature of the input files (if any) is known. 55 */ 56 57#define BUFFER_SIZE (64 * 1024) 58 59#ifndef NeXT_MOD 60static char in_buf[BUFFER_SIZE]; 61#endif /* !defined(NeXT_MOD) */ 62 63/* 64 * We use static data: the data area is not sharable. 65 */ 66 67FILE *f_in = NULL; /* JF do things the RIGHT way */ 68/* static JF remove static so app.c can use file_name */ 69char *file_name = NULL; 70 71/* These hooks accomodate most operating systems. */ 72 73void 74input_file_begin( 75void) 76{ 77 /* file_handle = -1; */ 78 f_in = (FILE *)0; 79} 80 81void 82input_file_end( 83void) 84{ 85} 86 87int /* Return BUFFER_SIZE. */ 88input_file_buffer_size( 89void) 90{ 91 return (BUFFER_SIZE); 92} 93 94int 95input_file_is_open( 96void) 97{ 98 /* return (file_handle >= 0); */ 99 return f_in!=(FILE *)0; 100} 101 102void 103input_file_open( 104char *filename, /* "" means use stdin. Must not be 0. */ 105int pre) 106{ 107 int c; 108 char buf[80]; 109 110 preprocess = pre; 111 112 assert( filename != 0 ); /* Filename may not be NULL. */ 113 if (filename [0]) { /* We have a file name. Suck it and see. */ 114 f_in=fopen(filename,"r"); 115 file_name=filename; 116 } else { /* use stdin for the input file. */ 117 f_in = stdin; 118 file_name = "{standard input}"; /* For error messages. */ 119 } 120 if (f_in==(FILE *)0) { 121 as_perror ("Can't open source file for input", file_name); 122 return; 123 } 124#ifdef NeXT_MOD /* .include feature */ 125 setbuffer(f_in, xmalloc(BUFFER_SIZE), BUFFER_SIZE); 126#else 127 setbuffer(f_in,in_buf,BUFFER_SIZE); 128#endif 129 c=getc_unlocked(f_in); 130 if(c=='#') { /* Begins with comment, may not want to preprocess */ 131 c=getc_unlocked(f_in); 132 if(c=='N') { 133 fgets(buf,80,f_in); 134 if(!strcmp(buf,"O_APP\n")) 135 preprocess=0; 136 if(!index(buf,'\n')) 137 ungetc('#',f_in); /* It was longer */ 138 else 139 ungetc('\n',f_in); 140 } else if(c=='\n') 141 ungetc('\n',f_in); 142 else 143 ungetc('#',f_in); 144 } else 145 ungetc(c,f_in); 146} 147 148char * 149input_file_give_next_buffer( 150char *where, /* Where to place 1st character of new buffer. */ 151int *give_next_size) 152{ 153 char * return_value; /* -> Last char of what we read, + 1. */ 154 register int size; 155 156 *give_next_size = BUFFER_SIZE; 157 if (f_in == (FILE *)0) 158 return 0; 159 /* 160 * fflush (stdin); could be done here if you want to synchronise 161 * stdin and stdout, for the case where our input file is stdin. 162 * Since the assembler shouldn't do any output to stdout, we 163 * don't bother to synch output and input. 164 */ 165 /* size = read (file_handle, where, BUFFER_SIZE); */ 166 if(preprocess) { 167 char *p; 168 int n; 169 int ch; 170 171 scrub_file=f_in; 172 for(p=where,n=BUFFER_SIZE;n;--n) { 173 ch=do_scrub_next_char(scrub_file); 174 if(ch==EOF) 175 break; 176 *p++=ch; 177 } 178 size=BUFFER_SIZE-n; 179 } else 180 size= fread(where,sizeof(char),BUFFER_SIZE,f_in); 181 if (size < 0) 182 { 183 as_perror ("Can't read source file: end-of-file faked.", file_name); 184 size = 0; 185 } 186 if (size) 187 return_value = where + size; 188 else 189 { 190#ifdef NeXT_MOD /* .include feature */ 191#ifdef __OPENSTEP__ 192 if(doing_include) 193 free (f_in->_base); 194#endif /* defined(__OPENSTEP__) */ 195#endif /* NeXT_MOD .include feature */ 196 if (fclose (f_in)) 197 as_perror ("Can't close source file -- continuing", file_name); 198 f_in = (FILE *)0; 199 return_value = 0; 200 } 201 return (return_value); 202} 203 204/* end: input_file.c */ 205