OSDN Git Service

13dc7631798db247ab93a7824ac7808c541546d1
[pf3gnuchains/gcc-fork.git] / gcc / c-pch.c
1 /* Precompiled header implementation for the C languages.
2    Copyright (C) 2000, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC 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 GNU CC 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 GNU CC; 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 "c-common.h"
27 #include "output.h"
28 #include "toplev.h"
29 #include "debug.h"
30 #include "c-pragma.h"
31 #include "ggc.h"
32
33 struct c_pch_header 
34 {
35   unsigned long asm_size;
36 };
37
38 static const char pch_ident[8] = "gpchC010";
39
40 static FILE *pch_outfile;
41
42 extern char *asm_file_name;
43 static long asm_file_startpos;
44
45 void
46 pch_init ()
47 {
48   FILE *f;
49   
50   if (pch_file)
51     {
52       /* We're precompiling a header file, so when it's actually used,
53          it'll be at least one level deep.  */
54       (*debug_hooks->start_source_file) (lineno, input_filename);
55
56       f = fopen (pch_file, "w+b");
57       if (f == NULL)
58         fatal_io_error ("can't open %s", pch_file);
59       pch_outfile = f;
60       
61       if (fwrite (pch_ident, sizeof (pch_ident), 1, f) != 1)
62         fatal_io_error ("can't write to %s", pch_file);
63
64       /* We need to be able to re-read the output.  */
65       /* The driver always provides a valid -o option.  */
66       if (asm_file_name == NULL
67           || strcmp (asm_file_name, "-") == 0)
68         fatal_error ("`%s' is not a valid output file", asm_file_name);
69
70       asm_file_startpos = ftell (asm_out_file);
71       
72       cpp_save_state (parse_in, f);
73     }
74 }
75
76 void
77 c_common_write_pch ()
78 {
79   char *buf;
80   long asm_file_end;
81   long written;
82   struct c_pch_header h;
83
84   cpp_write_pch_deps (parse_in, pch_outfile);
85
86   asm_file_end = ftell (asm_out_file);
87   h.asm_size = asm_file_end - asm_file_startpos;
88   
89   if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
90     fatal_io_error ("can't write %s", pch_file);
91   
92   buf = xmalloc (16384);
93   fflush (asm_out_file);
94
95   if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
96     fatal_io_error ("can't seek in %s", asm_file_name);
97
98   for (written = asm_file_startpos; written < asm_file_end; )
99     {
100       long size = asm_file_end - written;
101       if (size > 16384)
102         size = 16384;
103       if (fread (buf, size, 1, asm_out_file) != 1)
104         fatal_io_error ("can't read %s", asm_file_name);
105       if (fwrite (buf, size, 1, pch_outfile) != 1)
106         fatal_io_error ("can't write %s", pch_file);
107       written += size;
108     }
109   free (buf);
110
111   gt_pch_save (pch_outfile);
112   cpp_write_pch_state (parse_in, pch_outfile);
113
114   fclose (pch_outfile);
115 }
116
117 int
118 c_common_valid_pch (pfile, name, fd)
119      cpp_reader *pfile;
120      const char *name;
121      int fd;
122 {
123   int sizeread;
124   int result;
125   char ident[sizeof (pch_ident)];
126
127   if (! allow_pch)
128     return 2;
129
130   /* Perform a quick test of whether this is a valid
131      precompiled header for C.  */
132
133   sizeread = read (fd, ident, sizeof (pch_ident));
134   if (sizeread == -1)
135     {
136       fatal_io_error ("can't read %s", name);
137       return 2;
138     }
139   else if (sizeread != sizeof (pch_ident))
140     return 2;
141   
142   if (memcmp (ident, pch_ident, sizeof (pch_ident)) != 0)
143     {
144       if (cpp_get_options (pfile)->warn_invalid_pch)
145         {
146           if (memcmp (ident, pch_ident, 5) == 0)
147             /* It's a PCH, for the right language, but has the wrong version.
148              */
149             cpp_error (pfile, DL_WARNING, 
150                        "%s: not compatible with this GCC version", name);
151           else if (memcmp (ident, pch_ident, 4) == 0)
152             /* It's a PCH for the wrong language.  */
153             cpp_error (pfile, DL_WARNING, "%s: not for C language", name);
154           else 
155             /* Not any kind of PCH.  */
156             cpp_error (pfile, DL_WARNING, "%s: not a PCH file", name);
157         }
158       return 2;
159     }
160
161   /* Check the preprocessor macros are the same as when the PCH was
162      generated.  */
163   
164   result = cpp_valid_state (pfile, name, fd);
165   if (result == -1)
166     return 2;
167   else
168     return result == 0;
169 }
170
171 void
172 c_common_read_pch (pfile, name, fd, orig_name)
173      cpp_reader *pfile;
174      const char *name;
175      int fd;
176      const char *orig_name;
177 {
178   FILE *f;
179   struct c_pch_header h;
180   char *buf;
181   unsigned long written;
182   struct save_macro_data *smd;
183   
184   /* Before we wrote the file, we started a source file, so we have to start
185      one here to match.  */
186   (*debug_hooks->start_source_file) (lineno, orig_name);
187   
188   f = fdopen (fd, "rb");
189   if (f == NULL)
190     {
191       cpp_errno (pfile, DL_ERROR, "calling fdopen");
192       return;
193     }
194
195   allow_pch = 0;
196
197   if (fread (&h, sizeof (h), 1, f) != 1)
198     {
199       cpp_errno (pfile, DL_ERROR, "reading");
200       return;
201     }
202
203   buf = xmalloc (16384);
204   for (written = 0; written < h.asm_size; )
205     {
206       long size = h.asm_size - written;
207       if (size > 16384)
208         size = 16384;
209       if (fread (buf, size, 1, f) != 1
210           || fwrite (buf, size, 1, asm_out_file) != 1)
211         cpp_errno (pfile, DL_ERROR, "reading");
212       written += size;
213     }
214   free (buf);
215
216   cpp_prepare_state (pfile, &smd);
217
218   gt_pch_restore (f);
219
220   if (cpp_read_state (pfile, name, f, smd) != 0)
221     return;
222
223   fclose (f);
224
225   (*debug_hooks->end_source_file) (lineno);
226 }