Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / gnu / usr.bin / as / input-file.c
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, 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  * $FreeBSD: src/gnu/usr.bin/as/input-file.c,v 1.6 1999/08/27 23:34:17 peter Exp $
27  * $DragonFly: src/gnu/usr.bin/as/Attic/input-file.c,v 1.2 2003/06/17 04:25:44 dillon Exp $
28  */
29
30 #ifdef USG
31 #define setbuffer(stream, buf, size) setvbuf((stream), (buf), _IOFBF, (size))
32 #endif
33
34 #include <stdio.h>
35 #include <string.h>
36
37 #include "as.h"
38 #include "input-file.h"
39
40 /* This variable is non-zero if the file currently being read should be
41    preprocessed by app.  It is zero if the file can be read straight in.
42    */
43 int preprocess = 0;
44
45 /*
46  * This code opens a file, then delivers BUFFER_SIZE character
47  * chunks of the file on demand.
48  * BUFFER_SIZE is supposed to be a number chosen for speed.
49  * The caller only asks once what BUFFER_SIZE is, and asks before
50  * the nature of the input files (if any) is known.
51  */
52
53 #define BUFFER_SIZE (32 * 1024)
54
55 /*
56  * We use static data: the data area is not sharable.
57  */
58
59 FILE *f_in;
60 /* static JF remove static so app.c can use file_name */
61 char *  file_name;
62
63 /* Struct for saving the state of this module for file includes.  */
64 struct saved_file {
65         FILE *f_in;
66         char *file_name;
67         int     preprocess;
68         char *app_save;
69 };
70 \f
71 /* These hooks accomodate most operating systems. */
72
73 void input_file_begin() {
74         f_in = (FILE *)0;
75 }
76
77 void input_file_end () { }
78
79 /* Return BUFFER_SIZE. */
80 int input_file_buffer_size() {
81         return (BUFFER_SIZE);
82 }
83
84 int input_file_is_open() {
85         return f_in != (FILE *)0;
86 }
87
88 /* Push the state of our input, returning a pointer to saved info that
89    can be restored with input_file_pop ().  */
90 char *input_file_push () {
91         register struct saved_file *saved;
92
93         saved = (struct saved_file *)xmalloc (sizeof *saved);
94
95         saved->f_in             = f_in;
96         saved->file_name        = file_name;
97         saved->preprocess       = preprocess;
98         if (preprocess)
99             saved->app_save     = app_push ();
100
101         input_file_begin ();    /* Initialize for new file */
102
103         return (char *)saved;
104 }
105
106 void
107     input_file_pop (arg)
108 char *arg;
109 {
110         register struct saved_file *saved = (struct saved_file *)arg;
111
112         input_file_end ();      /* Close out old file */
113
114         f_in                    = saved->f_in;
115         file_name               = saved->file_name;
116         preprocess              = saved->preprocess;
117         if (preprocess)
118             app_pop              (saved->app_save);
119
120         free(arg);
121 }
122 \f
123 #ifdef DONTDEF          /* JF save old version in case we need it */
124 void
125     input_file_open (filename, preprocess, debugging)
126 char *  filename;       /* "" means use stdin. Must not be 0. */
127 int     preprocess;     /* TRUE if needs app. */
128 int     debugging;      /* TRUE if we are debugging assembler. */
129 {
130         assert( filename != 0 );        /* Filename may not be NULL. */
131         if (filename[0])
132             {                           /* We have a file name. Suck it and see. */
133                     file_handle = open (filename, O_RDONLY, 0);
134                     file_name = filename;
135             }
136         else
137             {                           /* use stdin for the input file. */
138                     file_handle = fileno (stdin);
139                     file_name = "{standard input}"; /* For error messages. */
140             }
141         if (file_handle < 0)
142             as_perror ("Can't open %s for reading", file_name);
143         if ( preprocess )
144             {
145                     /*
146                      * This code was written in haste for a frobbed BSD 4.2.
147                      * I have a flight to catch: will someone please do proper
148                      * error checks? - Dean.
149                      */
150                     int pid;
151                     char temporary_file_name[12];
152                     int fd;
153                     union wait  status;
154
155                     (void)strcpy (temporary_file_name, "#appXXXXXX");
156                     (void)mktemp (temporary_file_name);
157                     pid = vfork ();
158                     if (pid == -1)
159                         {
160                                 as_perror ("Vfork failed", file_name);
161                                 _exit (144);
162                         }
163                     if (pid == 0)
164                         {
165                                 (void)dup2 (file_handle, fileno(stdin));
166                                 fd = open (temporary_file_name, O_WRONLY + O_TRUNC + O_CREAT, 0666);
167                                 if (fd == -1)
168                                     {
169                                             (void)write(2,"Can't open temporary\n",21);
170                                             _exit (99);
171                                     }
172                                 (void)dup2 (fd, fileno(stdout));
173                                 /* JF for testing #define PREPROCESSOR "/lib/app" */
174 #define PREPROCESSOR "./app"
175                                 execl (PREPROCESSOR, PREPROCESSOR, 0);
176                                 execl ("app","app",0);
177                                 (void)write(2,"Exec of app failed.  Get help.\n",31);
178                                 (void)unlink(temporary_file_name);
179                                 _exit (11);
180                         }
181                     (void)wait (& status);
182                     if (status.w_status & 0xFF00)               /* JF was 0xF000, was wrong */
183                         {
184                                 file_handle = -1;
185                                 as_bad( "Can't preprocess file \"%s\", status = %xx", file_name, status.w_status );
186                         }
187                     else
188                         {
189                                 file_handle = open (temporary_file_name, O_RDONLY, 0);
190                                 if ( ! debugging && unlink(temporary_file_name))
191                                     as_perror ("Can't delete temp file %s", temporary_file_name);
192                         }
193                     if (file_handle == -1)
194                         as_perror ("Can't retrieve temp file %s", temporary_file_name);
195             }
196 }
197 #else
198
199 void
200     input_file_open (filename,pre)
201 char *  filename;       /* "" means use stdin. Must not be 0. */
202 int pre;
203 {
204         int     c;
205         char    buf[80];
206
207         preprocess = pre;
208
209         assert( filename != 0 );        /* Filename may not be NULL. */
210         if (filename[0]) {      /* We have a file name. Suck it and see. */
211                 f_in=fopen(filename,"r");
212                 file_name=filename;
213         } else {                        /* use stdin for the input file. */
214                 f_in = stdin;
215                 file_name = "{standard input}"; /* For error messages. */
216         }
217         if (f_in == (FILE *)0) {
218                 as_perror ("Can't open %s for reading", file_name);
219                 return;
220         }
221
222 #ifndef HO_VMS
223         /* Ask stdio to buffer our input at BUFFER_SIZE, with a dynamically
224            allocated buffer.  */
225         setvbuf(f_in, (char *)NULL, _IOFBF, BUFFER_SIZE);
226 #endif /* HO_VMS */
227
228         c = getc(f_in);
229         if (c == '#') { /* Begins with comment, may not want to preprocess */
230                 c = getc(f_in);
231                 if (c == 'N') {
232                         fgets(buf,80,f_in);
233                         if (!strcmp(buf,"O_APP\n"))
234                             preprocess=0;
235                         if (!strchr(buf,'\n'))
236                             ungetc('#',f_in);   /* It was longer */
237                         else
238                             ungetc('\n',f_in);
239                 } else if (c == '\n')
240                     ungetc('\n',f_in);
241                 else
242                     ungetc('#',f_in);
243         } else
244             ungetc(c,f_in);
245
246 #ifdef DONTDEF
247         if ( preprocess ) {
248                 char temporary_file_name[17];
249                 FILE    *f_out;
250
251                 (void)strcpy (temporary_file_name, "/tmp/#appXXXXXX");
252                 (void)mktemp (temporary_file_name);
253                 f_out=fopen(temporary_file_name,"w+");
254                 if (f_out == (FILE *)0)
255                     as_perror("Can't open temp file %s",temporary_file_name);
256
257                 /* JF this will have to be moved on any system that
258                    does not support removal of open files.  */
259                 (void)unlink(temporary_file_name);/* JF do it NOW */
260                 do_scrub(f_in,f_out);
261                 (void)fclose(f_in);     /* All done with it */
262                 (void)rewind(f_out);
263                 f_in=f_out;
264         }
265 #endif
266 }
267 #endif
268
269 /* Close input file.  */
270 void input_file_close() {
271         if (f_in != NULL) {
272                 fclose (f_in);
273         } /* don't close a null file pointer */
274         f_in = 0;
275 } /* input_file_close() */
276
277 char *
278     input_file_give_next_buffer (where)
279 char *          where;  /* Where to place 1st character of new buffer. */
280 {
281         char *  return_value;   /* -> Last char of what we read, + 1. */
282         register int    size;
283
284         if (f_in == (FILE *)0)
285             return 0;
286         /*
287          * fflush (stdin); could be done here if you want to synchronise
288          * stdin and stdout, for the case where our input file is stdin.
289          * Since the assembler shouldn't do any output to stdout, we
290          * don't bother to synch output and input.
291          */
292         if (preprocess) {
293                 char *p;
294                 int n;
295                 int ch;
296                 extern FILE *scrub_file;
297
298                 scrub_file=f_in;
299                 for (p = where, n = BUFFER_SIZE; n; --n) {
300
301                         ch = do_scrub_next_char(scrub_from_file, scrub_to_file);
302                         if (ch == EOF)
303                             break;
304                         *p++=ch;
305                 }
306                 size=BUFFER_SIZE-n;
307         } else
308             size= fread(where,sizeof(char),BUFFER_SIZE,f_in);
309         if (size < 0)
310             {
311                     as_perror ("Can't read from %s", file_name);
312                     size = 0;
313             }
314         if (size)
315             return_value = where + size;
316         else
317             {
318                     if (fclose (f_in))
319                         as_perror ("Can't close %s", file_name);
320                     f_in = (FILE *)0;
321                     return_value = 0;
322             }
323         return (return_value);
324 }
325
326 /* end of input-file.c */