OSDN Git Service

* c-pch.c (c_common_write_pch): Flush asm_out_file to allow for
[pf3gnuchains/gcc-fork.git] / gcc / c-pch.c
1 /* Precompiled header implementation for the C languages.
2    Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC 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 GCC 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 GCC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "cpplib.h"
25 #include "tree.h"
26 #include "flags.h"
27 #include "c-common.h"
28 #include "output.h"
29 #include "toplev.h"
30 #include "debug.h"
31 #include "c-pragma.h"
32 #include "ggc.h"
33 #include "langhooks.h"
34
35 struct c_pch_validity
36 {
37   unsigned char debug_info_type;
38 };
39
40 struct c_pch_header 
41 {
42   unsigned long asm_size;
43 };
44
45 #define IDENT_LENGTH 8
46
47 static FILE *pch_outfile;
48
49 static long asm_file_startpos;
50
51 static const char *get_ident (void);
52
53 /* Compute an appropriate 8-byte magic number for the PCH file, so that
54    utilities like file(1) can identify it, and so that GCC can quickly
55    ignore non-PCH files and PCH files that are of a completely different
56    format.  */
57
58 static const char *
59 get_ident(void)
60 {
61   static char result[IDENT_LENGTH];
62   static const char template[IDENT_LENGTH] = "gpch.011";
63   
64   memcpy (result, template, IDENT_LENGTH);
65   if (c_language == clk_c)
66     result[4] = flag_objc ? 'o' : 'C';
67   else if (c_language == clk_cplusplus)
68     result[4] = flag_objc ? 'O' : '+';
69   else
70     abort ();
71   return result;
72 }
73
74 /* Prepare to write a PCH file.  This is called at the start of 
75    compilation.  */
76
77 void
78 pch_init (void)
79 {
80   FILE *f;
81   struct c_pch_validity v;
82   
83   if (! pch_file)
84     return;
85   
86   f = fopen (pch_file, "w+b");
87   if (f == NULL)
88     fatal_error ("can't open %s: %m", pch_file);
89   pch_outfile = f;
90   
91   v.debug_info_type = write_symbols;
92   if (fwrite (get_ident(), IDENT_LENGTH, 1, f) != 1
93       || fwrite (&v, sizeof (v), 1, f) != 1)
94     fatal_error ("can't write to %s: %m", pch_file);
95
96   /* We need to be able to re-read the output.  */
97   /* The driver always provides a valid -o option.  */
98   if (asm_file_name == NULL
99       || strcmp (asm_file_name, "-") == 0)
100     fatal_error ("`%s' is not a valid output file", asm_file_name);
101   
102   asm_file_startpos = ftell (asm_out_file);
103   
104   /* Let the debugging format deal with the PCHness.  */
105   (*debug_hooks->handle_pch) (0);
106   
107   cpp_save_state (parse_in, f);
108 }
109
110 /* Write the PCH file.  This is called at the end of a compilation which
111    will produce a PCH file.  */
112
113 void
114 c_common_write_pch (void)
115 {
116   char *buf;
117   long asm_file_end;
118   long written;
119   struct c_pch_header h;
120
121   (*debug_hooks->handle_pch) (1);
122
123   cpp_write_pch_deps (parse_in, pch_outfile);
124
125   asm_file_end = ftell (asm_out_file);
126   h.asm_size = asm_file_end - asm_file_startpos;
127   
128   if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
129     fatal_error ("can't write %s: %m", pch_file);
130   
131   buf = xmalloc (16384);
132   fflush (asm_out_file);
133
134   if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
135     fatal_error ("can't seek in %s: %m", asm_file_name);
136
137   for (written = asm_file_startpos; written < asm_file_end; )
138     {
139       long size = asm_file_end - written;
140       if (size > 16384)
141         size = 16384;
142       if (fread (buf, size, 1, asm_out_file) != 1)
143         fatal_error ("can't read %s: %m", asm_file_name);
144       if (fwrite (buf, size, 1, pch_outfile) != 1)
145         fatal_error ("can't write %s: %m", pch_file);
146       written += size;
147     }
148   free (buf);
149   /* asm_out_file can be written afterwards, so must be flushed first.  */
150   fflush (asm_out_file);
151
152   gt_pch_save (pch_outfile);
153   cpp_write_pch_state (parse_in, pch_outfile);
154
155   fclose (pch_outfile);
156 }
157
158 /* Check the PCH file called NAME, open on FD, to see if it can be used
159    in this compilation.  */
160
161 int
162 c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
163 {
164   int sizeread;
165   int result;
166   char ident[IDENT_LENGTH];
167   const char *pch_ident;
168   struct c_pch_validity v;
169
170   if (! allow_pch)
171     return 2;
172
173   /* Perform a quick test of whether this is a valid
174      precompiled header for the current language.  */
175
176   sizeread = read (fd, ident, IDENT_LENGTH);
177   if (sizeread == -1)
178     fatal_error ("can't read %s: %m", name);
179   else if (sizeread != IDENT_LENGTH)
180     return 2;
181   
182   pch_ident = get_ident();
183   if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
184     {
185       if (cpp_get_options (pfile)->warn_invalid_pch)
186         {
187           if (memcmp (ident, pch_ident, 5) == 0)
188             /* It's a PCH, for the right language, but has the wrong version.
189              */
190             cpp_error (pfile, DL_WARNING, 
191                        "%s: not compatible with this GCC version", name);
192           else if (memcmp (ident, pch_ident, 4) == 0)
193             /* It's a PCH for the wrong language.  */
194             cpp_error (pfile, DL_WARNING, "%s: not for %s", name,
195                        lang_hooks.name);
196           else 
197             /* Not any kind of PCH.  */
198             cpp_error (pfile, DL_WARNING, "%s: not a PCH file", name);
199         }
200       return 2;
201     }
202
203   if (read (fd, &v, sizeof (v)) != sizeof (v))
204     fatal_error ("can't read %s: %m", name);
205
206   /* The allowable debug info combinations are that either the PCH file
207      was built with the same as is being used now, or the PCH file was
208      built for some kind of debug info but now none is in use.  */
209   if (v.debug_info_type != write_symbols
210       && write_symbols != NO_DEBUG)
211     {
212       if (cpp_get_options (pfile)->warn_invalid_pch)
213         cpp_error (pfile, DL_WARNING, 
214                    "%s: created with -g%s, but used with -g%s", name,
215                    debug_type_names[v.debug_info_type],
216                    debug_type_names[write_symbols]);
217       return 2;
218     }
219
220   /* Check the preprocessor macros are the same as when the PCH was
221      generated.  */
222   
223   result = cpp_valid_state (pfile, name, fd);
224   if (result == -1)
225     return 2;
226   else
227     return result == 0;
228 }
229
230 /* Load in the PCH file NAME, open on FD.  It was originally searched for
231    by ORIG_NAME.  */
232
233 void
234 c_common_read_pch (cpp_reader *pfile, const char *name,
235                    int fd, const char *orig_name ATTRIBUTE_UNUSED)
236 {
237   FILE *f;
238   struct c_pch_header h;
239   char *buf;
240   unsigned long written;
241   struct save_macro_data *smd;
242   
243   f = fdopen (fd, "rb");
244   if (f == NULL)
245     {
246       cpp_errno (pfile, DL_ERROR, "calling fdopen");
247       return;
248     }
249
250   allow_pch = 0;
251
252   if (fread (&h, sizeof (h), 1, f) != 1)
253     {
254       cpp_errno (pfile, DL_ERROR, "reading");
255       return;
256     }
257
258   buf = xmalloc (16384);
259   for (written = 0; written < h.asm_size; )
260     {
261       long size = h.asm_size - written;
262       if (size > 16384)
263         size = 16384;
264       if (fread (buf, size, 1, f) != 1
265           || fwrite (buf, size, 1, asm_out_file) != 1)
266         cpp_errno (pfile, DL_ERROR, "reading");
267       written += size;
268     }
269   free (buf);
270
271   cpp_prepare_state (pfile, &smd);
272
273   gt_pch_restore (f);
274
275   if (cpp_read_state (pfile, name, f, smd) != 0)
276     return;
277
278   fclose (f);
279 }