]>
Commit | Line | Data |
---|---|---|
17211ab5 | 1 | /* Precompiled header implementation for the C languages. |
2d593c86 | 2 | Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. |
17211ab5 | 3 | |
54a7b573 | 4 | This file is part of GCC. |
17211ab5 | 5 | |
54a7b573 | 6 | GCC is free software; you can redistribute it and/or modify |
17211ab5 | 7 | it under the terms of the GNU General Public License as published by |
9dcd6f09 | 8 | the Free Software Foundation; either version 3, or (at your option) |
17211ab5 GK |
9 | any later version. |
10 | ||
54a7b573 | 11 | GCC is distributed in the hope that it will be useful, |
17211ab5 GK |
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 | |
9dcd6f09 NC |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ | |
17211ab5 GK |
19 | |
20 | #include "config.h" | |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
7451756f | 23 | #include "version.h" |
17211ab5 GK |
24 | #include "cpplib.h" |
25 | #include "tree.h" | |
df026186 | 26 | #include "flags.h" |
17211ab5 GK |
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" | |
8643e92d | 33 | #include "langhooks.h" |
18c81520 | 34 | #include "hosthooks.h" |
7bb1ad93 | 35 | #include "target.h" |
5ffeb913 | 36 | #include "opts.h" |
17211ab5 | 37 | |
54e109ed GK |
38 | /* This is a list of flag variables that must match exactly, and their |
39 | names for the error message. The possible values for *flag_var must | |
40 | fit in a 'signed char'. */ | |
41 | ||
c22cacf3 | 42 | static const struct c_pch_matching |
54e109ed GK |
43 | { |
44 | int *flag_var; | |
45 | const char *flag_name; | |
46 | } pch_matching[] = { | |
47 | { &flag_exceptions, "-fexceptions" }, | |
54e109ed GK |
48 | }; |
49 | ||
50 | enum { | |
51 | MATCH_SIZE = ARRAY_SIZE (pch_matching) | |
52 | }; | |
53 | ||
3fd30b88 GK |
54 | /* The value of the checksum in the dummy compiler that is actually |
55 | checksummed. That compiler should never be run. */ | |
56 | static const char no_checksum[16] = { 0 }; | |
7451756f | 57 | |
3fd30b88 | 58 | /* Information about flags and suchlike that affect PCH validity. |
7bb1ad93 | 59 | |
3fd30b88 GK |
60 | Before this structure is read, both an initial 8-character identification |
61 | string, and a 16-byte checksum, have been read and validated. */ | |
7451756f | 62 | |
df026186 GK |
63 | struct c_pch_validity |
64 | { | |
65 | unsigned char debug_info_type; | |
54e109ed | 66 | signed char match[MATCH_SIZE]; |
926a822f | 67 | void (*pch_init) (void); |
7bb1ad93 | 68 | size_t target_data_length; |
df026186 GK |
69 | }; |
70 | ||
c22cacf3 | 71 | struct c_pch_header |
17211ab5 GK |
72 | { |
73 | unsigned long asm_size; | |
74 | }; | |
75 | ||
8643e92d | 76 | #define IDENT_LENGTH 8 |
17211ab5 | 77 | |
7451756f | 78 | /* The file we'll be writing the PCH to. */ |
17211ab5 GK |
79 | static FILE *pch_outfile; |
80 | ||
7451756f | 81 | /* The position in the assembler output file when pch_init was called. */ |
70f8b89f | 82 | static long asm_file_startpos; |
17211ab5 | 83 | |
2f6e4e97 | 84 | static const char *get_ident (void); |
8643e92d | 85 | |
df026186 GK |
86 | /* Compute an appropriate 8-byte magic number for the PCH file, so that |
87 | utilities like file(1) can identify it, and so that GCC can quickly | |
88 | ignore non-PCH files and PCH files that are of a completely different | |
89 | format. */ | |
90 | ||
8643e92d | 91 | static const char * |
3f75a254 | 92 | get_ident (void) |
8643e92d GK |
93 | { |
94 | static char result[IDENT_LENGTH]; | |
48c54229 | 95 | static const char templ[IDENT_LENGTH] = "gpch.013"; |
37fa72e9 | 96 | static const char c_language_chars[] = "Co+O"; |
c22cacf3 | 97 | |
48c54229 | 98 | memcpy (result, templ, IDENT_LENGTH); |
37fa72e9 NB |
99 | result[4] = c_language_chars[c_language]; |
100 | ||
8643e92d GK |
101 | return result; |
102 | } | |
103 | ||
3fd30b88 | 104 | /* Prepare to write a PCH file, if one is being written. This is |
c22cacf3 | 105 | called at the start of compilation. |
3fd30b88 GK |
106 | |
107 | Also, print out the executable checksum if -fverbose-asm is in effect. */ | |
df026186 | 108 | |
17211ab5 | 109 | void |
2f6e4e97 | 110 | pch_init (void) |
17211ab5 GK |
111 | { |
112 | FILE *f; | |
df026186 | 113 | struct c_pch_validity v; |
7bb1ad93 | 114 | void *target_validity; |
7a681365 | 115 | static const char partial_pch[IDENT_LENGTH] = "gpcWrite"; |
c22cacf3 | 116 | |
3fd30b88 GK |
117 | #ifdef ASM_COMMENT_START |
118 | if (flag_verbose_asm) | |
119 | { | |
120 | fprintf (asm_out_file, "%s ", ASM_COMMENT_START); | |
121 | c_common_print_pch_checksum (asm_out_file); | |
122 | fputc ('\n', asm_out_file); | |
123 | } | |
124 | #endif | |
c22cacf3 | 125 | |
3f75a254 | 126 | if (!pch_file) |
df026186 | 127 | return; |
c22cacf3 | 128 | |
df026186 GK |
129 | f = fopen (pch_file, "w+b"); |
130 | if (f == NULL) | |
9e637a26 | 131 | fatal_error ("can%'t create precompiled header %s: %m", pch_file); |
df026186 | 132 | pch_outfile = f; |
366de0ce | 133 | |
3fd30b88 | 134 | gcc_assert (memcmp (executable_checksum, no_checksum, 16) != 0); |
c22cacf3 | 135 | |
df026186 | 136 | v.debug_info_type = write_symbols; |
54e109ed GK |
137 | { |
138 | size_t i; | |
139 | for (i = 0; i < MATCH_SIZE; i++) | |
140 | { | |
141 | v.match[i] = *pch_matching[i].flag_var; | |
366de0ce | 142 | gcc_assert (v.match[i] == *pch_matching[i].flag_var); |
54e109ed GK |
143 | } |
144 | } | |
926a822f | 145 | v.pch_init = &pch_init; |
7bb1ad93 | 146 | target_validity = targetm.get_pch_validity (&v.target_data_length); |
c22cacf3 | 147 | |
7a681365 | 148 | if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1 |
3fd30b88 | 149 | || fwrite (executable_checksum, 16, 1, f) != 1 |
7451756f | 150 | || fwrite (&v, sizeof (v), 1, f) != 1 |
7bb1ad93 | 151 | || fwrite (target_validity, v.target_data_length, 1, f) != 1) |
9e637a26 | 152 | fatal_error ("can%'t write to %s: %m", pch_file); |
df026186 GK |
153 | |
154 | /* We need to be able to re-read the output. */ | |
155 | /* The driver always provides a valid -o option. */ | |
156 | if (asm_file_name == NULL | |
157 | || strcmp (asm_file_name, "-") == 0) | |
971801ff | 158 | fatal_error ("%qs is not a valid output file", asm_file_name); |
c22cacf3 | 159 | |
df026186 | 160 | asm_file_startpos = ftell (asm_out_file); |
c22cacf3 | 161 | |
df026186 GK |
162 | /* Let the debugging format deal with the PCHness. */ |
163 | (*debug_hooks->handle_pch) (0); | |
c22cacf3 | 164 | |
df026186 | 165 | cpp_save_state (parse_in, f); |
17211ab5 GK |
166 | } |
167 | ||
df026186 GK |
168 | /* Write the PCH file. This is called at the end of a compilation which |
169 | will produce a PCH file. */ | |
170 | ||
17211ab5 | 171 | void |
2f6e4e97 | 172 | c_common_write_pch (void) |
17211ab5 GK |
173 | { |
174 | char *buf; | |
70f8b89f KG |
175 | long asm_file_end; |
176 | long written; | |
17211ab5 GK |
177 | struct c_pch_header h; |
178 | ||
33b49800 GK |
179 | (*debug_hooks->handle_pch) (1); |
180 | ||
17211ab5 GK |
181 | cpp_write_pch_deps (parse_in, pch_outfile); |
182 | ||
70f8b89f | 183 | asm_file_end = ftell (asm_out_file); |
17211ab5 | 184 | h.asm_size = asm_file_end - asm_file_startpos; |
c22cacf3 | 185 | |
17211ab5 | 186 | if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1) |
9e637a26 | 187 | fatal_error ("can%'t write %s: %m", pch_file); |
c22cacf3 | 188 | |
cceb1885 | 189 | buf = XNEWVEC (char, 16384); |
17211ab5 | 190 | |
70f8b89f | 191 | if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0) |
9e637a26 | 192 | fatal_error ("can%'t seek in %s: %m", asm_file_name); |
17211ab5 GK |
193 | |
194 | for (written = asm_file_startpos; written < asm_file_end; ) | |
195 | { | |
70f8b89f | 196 | long size = asm_file_end - written; |
17211ab5 GK |
197 | if (size > 16384) |
198 | size = 16384; | |
199 | if (fread (buf, size, 1, asm_out_file) != 1) | |
9e637a26 | 200 | fatal_error ("can%'t read %s: %m", asm_file_name); |
17211ab5 | 201 | if (fwrite (buf, size, 1, pch_outfile) != 1) |
9e637a26 | 202 | fatal_error ("can%'t write %s: %m", pch_file); |
17211ab5 GK |
203 | written += size; |
204 | } | |
205 | free (buf); | |
90aa6719 DS |
206 | /* asm_out_file can be written afterwards, so fseek to clear |
207 | _IOREAD flag. */ | |
208 | if (fseek (asm_out_file, 0, SEEK_END) != 0) | |
9e637a26 | 209 | fatal_error ("can%'t seek in %s: %m", asm_file_name); |
17211ab5 GK |
210 | |
211 | gt_pch_save (pch_outfile); | |
212 | cpp_write_pch_state (parse_in, pch_outfile); | |
213 | ||
7a681365 GK |
214 | if (fseek (pch_outfile, 0, SEEK_SET) != 0 |
215 | || fwrite (get_ident (), IDENT_LENGTH, 1, pch_outfile) != 1) | |
9e637a26 | 216 | fatal_error ("can%'t write %s: %m", pch_file); |
7a681365 | 217 | |
17211ab5 GK |
218 | fclose (pch_outfile); |
219 | } | |
220 | ||
7bb1ad93 GK |
221 | /* Check the PCH file called NAME, open on FD, to see if it can be |
222 | used in this compilation. Return 1 if valid, 0 if the file can't | |
223 | be used now but might be if it's seen later in the compilation, and | |
224 | 2 if this file could never be used in the compilation. */ | |
df026186 | 225 | |
17211ab5 | 226 | int |
2f6e4e97 | 227 | c_common_valid_pch (cpp_reader *pfile, const char *name, int fd) |
17211ab5 GK |
228 | { |
229 | int sizeread; | |
230 | int result; | |
3fd30b88 | 231 | char ident[IDENT_LENGTH + 16]; |
8643e92d | 232 | const char *pch_ident; |
df026186 | 233 | struct c_pch_validity v; |
17211ab5 | 234 | |
17211ab5 | 235 | /* Perform a quick test of whether this is a valid |
df026186 | 236 | precompiled header for the current language. */ |
17211ab5 | 237 | |
3fd30b88 GK |
238 | gcc_assert (memcmp (executable_checksum, no_checksum, 16) != 0); |
239 | ||
240 | sizeread = read (fd, ident, IDENT_LENGTH + 16); | |
17211ab5 | 241 | if (sizeread == -1) |
9e637a26 | 242 | fatal_error ("can%'t read %s: %m", name); |
3fd30b88 GK |
243 | else if (sizeread != IDENT_LENGTH + 16) |
244 | { | |
bb1f73c2 AP |
245 | if (cpp_get_options (pfile)->warn_invalid_pch) |
246 | cpp_error (pfile, CPP_DL_WARNING, "%s: too short to be a PCH file", | |
247 | name); | |
3fd30b88 GK |
248 | return 2; |
249 | } | |
c22cacf3 | 250 | |
8643e92d GK |
251 | pch_ident = get_ident(); |
252 | if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0) | |
17211ab5 GK |
253 | { |
254 | if (cpp_get_options (pfile)->warn_invalid_pch) | |
255 | { | |
256 | if (memcmp (ident, pch_ident, 5) == 0) | |
257 | /* It's a PCH, for the right language, but has the wrong version. | |
258 | */ | |
c22cacf3 | 259 | cpp_error (pfile, CPP_DL_WARNING, |
17211ab5 GK |
260 | "%s: not compatible with this GCC version", name); |
261 | else if (memcmp (ident, pch_ident, 4) == 0) | |
262 | /* It's a PCH for the wrong language. */ | |
0527bc4e | 263 | cpp_error (pfile, CPP_DL_WARNING, "%s: not for %s", name, |
8643e92d | 264 | lang_hooks.name); |
c22cacf3 | 265 | else |
17211ab5 | 266 | /* Not any kind of PCH. */ |
0527bc4e | 267 | cpp_error (pfile, CPP_DL_WARNING, "%s: not a PCH file", name); |
17211ab5 GK |
268 | } |
269 | return 2; | |
270 | } | |
3fd30b88 | 271 | if (memcmp (ident + IDENT_LENGTH, executable_checksum, 16) != 0) |
7451756f GK |
272 | { |
273 | if (cpp_get_options (pfile)->warn_invalid_pch) | |
0527bc4e | 274 | cpp_error (pfile, CPP_DL_WARNING, |
3fd30b88 | 275 | "%s: created by a different GCC executable", name); |
7451756f GK |
276 | return 2; |
277 | } | |
278 | ||
3fd30b88 GK |
279 | /* At this point, we know it's a PCH file created by this |
280 | executable, so it ought to be long enough that we can read a | |
281 | c_pch_validity structure. */ | |
282 | if (read (fd, &v, sizeof (v)) != sizeof (v)) | |
283 | fatal_error ("can%'t read %s: %m", name); | |
284 | ||
df026186 GK |
285 | /* The allowable debug info combinations are that either the PCH file |
286 | was built with the same as is being used now, or the PCH file was | |
287 | built for some kind of debug info but now none is in use. */ | |
288 | if (v.debug_info_type != write_symbols | |
289 | && write_symbols != NO_DEBUG) | |
290 | { | |
291 | if (cpp_get_options (pfile)->warn_invalid_pch) | |
c22cacf3 | 292 | cpp_error (pfile, CPP_DL_WARNING, |
df026186 GK |
293 | "%s: created with -g%s, but used with -g%s", name, |
294 | debug_type_names[v.debug_info_type], | |
295 | debug_type_names[write_symbols]); | |
296 | return 2; | |
297 | } | |
298 | ||
54e109ed GK |
299 | /* Check flags that must match exactly. */ |
300 | { | |
301 | size_t i; | |
302 | for (i = 0; i < MATCH_SIZE; i++) | |
303 | if (*pch_matching[i].flag_var != v.match[i]) | |
304 | { | |
305 | if (cpp_get_options (pfile)->warn_invalid_pch) | |
c22cacf3 | 306 | cpp_error (pfile, CPP_DL_WARNING, |
54e109ed GK |
307 | "%s: settings for %s do not match", name, |
308 | pch_matching[i].flag_name); | |
309 | return 2; | |
310 | } | |
311 | } | |
312 | ||
926a822f MM |
313 | /* If the text segment was not loaded at the same address as it was |
314 | when the PCH file was created, function pointers loaded from the | |
315 | PCH will not be valid. We could in theory remap all the function | |
c22cacf3 | 316 | pointers, but no support for that exists at present. |
3fd30b88 GK |
317 | Since we have the same executable, it should only be necessary to |
318 | check one function. */ | |
926a822f MM |
319 | if (v.pch_init != &pch_init) |
320 | { | |
321 | if (cpp_get_options (pfile)->warn_invalid_pch) | |
c22cacf3 | 322 | cpp_error (pfile, CPP_DL_WARNING, |
926a822f MM |
323 | "%s: had text segment at different address", name); |
324 | return 2; | |
325 | } | |
326 | ||
7bb1ad93 GK |
327 | /* Check the target-specific validity data. */ |
328 | { | |
329 | void *this_file_data = xmalloc (v.target_data_length); | |
330 | const char *msg; | |
c22cacf3 | 331 | |
7bb1ad93 GK |
332 | if ((size_t) read (fd, this_file_data, v.target_data_length) |
333 | != v.target_data_length) | |
9e637a26 | 334 | fatal_error ("can%'t read %s: %m", name); |
7bb1ad93 GK |
335 | msg = targetm.pch_valid_p (this_file_data, v.target_data_length); |
336 | free (this_file_data); | |
337 | if (msg != NULL) | |
338 | { | |
339 | if (cpp_get_options (pfile)->warn_invalid_pch) | |
0527bc4e | 340 | cpp_error (pfile, CPP_DL_WARNING, "%s: %s", name, msg); |
7bb1ad93 GK |
341 | return 2; |
342 | } | |
343 | } | |
344 | ||
17211ab5 GK |
345 | /* Check the preprocessor macros are the same as when the PCH was |
346 | generated. */ | |
c22cacf3 | 347 | |
17211ab5 GK |
348 | result = cpp_valid_state (pfile, name, fd); |
349 | if (result == -1) | |
350 | return 2; | |
351 | else | |
352 | return result == 0; | |
353 | } | |
354 | ||
4684cd27 MM |
355 | /* If non-NULL, this function is called after a precompile header file |
356 | is loaded. */ | |
357 | void (*lang_post_pch_load) (void); | |
358 | ||
df026186 GK |
359 | /* Load in the PCH file NAME, open on FD. It was originally searched for |
360 | by ORIG_NAME. */ | |
361 | ||
17211ab5 | 362 | void |
2f6e4e97 AJ |
363 | c_common_read_pch (cpp_reader *pfile, const char *name, |
364 | int fd, const char *orig_name ATTRIBUTE_UNUSED) | |
17211ab5 GK |
365 | { |
366 | FILE *f; | |
367 | struct c_pch_header h; | |
17211ab5 | 368 | struct save_macro_data *smd; |
5ffeb913 | 369 | expanded_location saved_loc; |
b3e200e1 | 370 | bool saved_trace_includes; |
c22cacf3 | 371 | |
17211ab5 GK |
372 | f = fdopen (fd, "rb"); |
373 | if (f == NULL) | |
374 | { | |
0527bc4e | 375 | cpp_errno (pfile, CPP_DL_ERROR, "calling fdopen"); |
d4c32e1d | 376 | close (fd); |
17211ab5 GK |
377 | return; |
378 | } | |
379 | ||
18c81520 | 380 | cpp_get_callbacks (parse_in)->valid_pch = NULL; |
17211ab5 GK |
381 | |
382 | if (fread (&h, sizeof (h), 1, f) != 1) | |
383 | { | |
0527bc4e | 384 | cpp_errno (pfile, CPP_DL_ERROR, "reading"); |
d4c32e1d | 385 | fclose (f); |
17211ab5 GK |
386 | return; |
387 | } | |
388 | ||
c0d578e6 | 389 | if (!flag_preprocess_only) |
17211ab5 | 390 | { |
c0d578e6 | 391 | unsigned long written; |
cceb1885 | 392 | char * buf = XNEWVEC (char, 16384); |
c0d578e6 GK |
393 | |
394 | for (written = 0; written < h.asm_size; ) | |
395 | { | |
396 | long size = h.asm_size - written; | |
397 | if (size > 16384) | |
398 | size = 16384; | |
399 | if (fread (buf, size, 1, f) != 1 | |
400 | || fwrite (buf, size, 1, asm_out_file) != 1) | |
401 | cpp_errno (pfile, CPP_DL_ERROR, "reading"); | |
402 | written += size; | |
403 | } | |
404 | free (buf); | |
405 | } | |
406 | else | |
407 | { | |
408 | /* If we're preprocessing, don't write to a NULL | |
409 | asm_out_file. */ | |
410 | if (fseek (f, h.asm_size, SEEK_CUR) != 0) | |
411 | cpp_errno (pfile, CPP_DL_ERROR, "seeking"); | |
17211ab5 | 412 | } |
17211ab5 | 413 | |
5ffeb913 | 414 | /* Save the location and then restore it after reading the PCH. */ |
5ffeb913 | 415 | saved_loc = expand_location (line_table->highest_line); |
b3e200e1 | 416 | saved_trace_includes = line_table->trace_includes; |
5ffeb913 | 417 | |
17211ab5 GK |
418 | cpp_prepare_state (pfile, &smd); |
419 | ||
420 | gt_pch_restore (f); | |
421 | ||
422 | if (cpp_read_state (pfile, name, f, smd) != 0) | |
d4c32e1d JJ |
423 | { |
424 | fclose (f); | |
425 | return; | |
426 | } | |
17211ab5 GK |
427 | |
428 | fclose (f); | |
c22cacf3 | 429 | |
b3e200e1 | 430 | line_table->trace_includes = saved_trace_includes; |
5ffeb913 TT |
431 | cpp_set_line_map (pfile, line_table); |
432 | linemap_add (line_table, LC_RENAME, 0, saved_loc.file, saved_loc.line); | |
433 | ||
4684cd27 | 434 | /* Give the front end a chance to take action after a PCH file has |
6cb38cd4 | 435 | been loaded. */ |
4684cd27 MM |
436 | if (lang_post_pch_load) |
437 | (*lang_post_pch_load) (); | |
17211ab5 | 438 | } |
18c81520 GK |
439 | |
440 | /* Indicate that no more PCH files should be read. */ | |
441 | ||
442 | void | |
443 | c_common_no_more_pch (void) | |
444 | { | |
445 | if (cpp_get_callbacks (parse_in)->valid_pch) | |
446 | { | |
447 | cpp_get_callbacks (parse_in)->valid_pch = NULL; | |
4d0c31e6 | 448 | host_hooks.gt_pch_use_address (NULL, 0, -1, 0); |
18c81520 GK |
449 | } |
450 | } | |
c0d578e6 GK |
451 | |
452 | /* Handle #pragma GCC pch_preprocess, to load in the PCH file. */ | |
453 | ||
454 | #ifndef O_BINARY | |
455 | # define O_BINARY 0 | |
456 | #endif | |
457 | ||
458 | void | |
bc4071dd | 459 | c_common_pch_pragma (cpp_reader *pfile, const char *name) |
c0d578e6 | 460 | { |
c0d578e6 GK |
461 | int fd; |
462 | ||
3f75a254 | 463 | if (!cpp_get_options (pfile)->preprocessed) |
c0d578e6 GK |
464 | { |
465 | error ("pch_preprocess pragma should only be used with -fpreprocessed"); | |
1f5b3869 | 466 | inform (input_location, "use #include instead"); |
c0d578e6 GK |
467 | return; |
468 | } | |
469 | ||
c0d578e6 GK |
470 | fd = open (name, O_RDONLY | O_BINARY, 0666); |
471 | if (fd == -1) | |
ab532386 | 472 | fatal_error ("%s: couldn%'t open PCH file: %m", name); |
c22cacf3 | 473 | |
c0d578e6 GK |
474 | if (c_common_valid_pch (pfile, name, fd) != 1) |
475 | { | |
476 | if (!cpp_get_options (pfile)->warn_invalid_pch) | |
1f5b3869 | 477 | inform (input_location, "use -Winvalid-pch for more information"); |
c0d578e6 GK |
478 | fatal_error ("%s: PCH file was invalid", name); |
479 | } | |
c22cacf3 | 480 | |
c0d578e6 | 481 | c_common_read_pch (pfile, name, fd, name); |
c22cacf3 | 482 | |
c0d578e6 GK |
483 | close (fd); |
484 | } | |
3fd30b88 GK |
485 | |
486 | /* Print out executable_checksum[]. */ | |
487 | ||
488 | void | |
489 | c_common_print_pch_checksum (FILE *f) | |
490 | { | |
491 | int i; | |
492 | fputs ("Compiler executable checksum: ", f); | |
493 | for (i = 0; i < 16; i++) | |
494 | fprintf (f, "%02x", executable_checksum[i]); | |
495 | putc ('\n', f); | |
496 | } |