]>
Commit | Line | Data |
---|---|---|
bb09dca5 | 1 | /* Code to maintain a C++ template repository. |
ad87de1e | 2 | Copyright (C) 1995, 1997 Free Software Foundation, Inc. |
bb09dca5 | 3 | Contributed by Jason Merrill (jason@cygnus.com) |
4 | ||
5 | This file is part of GNU CC. | |
6 | ||
7 | GNU CC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GNU CC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GNU CC; see the file COPYING. If not, write to | |
c58d4270 | 19 | the Free Software Foundation, 59 Temple Place - Suite 330, |
20 | Boston, MA 02111-1307, USA. */ | |
bb09dca5 | 21 | |
22 | /* My strategy here is as follows: | |
23 | ||
24 | Everything should be emitted in a translation unit where it is used. | |
25 | The results of the automatic process should be easily reproducible with | |
11682839 | 26 | explicit code. */ |
bb09dca5 | 27 | |
11682839 | 28 | #include "config.h" |
39c8ac16 | 29 | #include <stdio.h> |
bb09dca5 | 30 | #include "tree.h" |
31 | #include "cp-tree.h" | |
32 | #include "input.h" | |
3e1ffd94 | 33 | #include "obstack.h" |
bb09dca5 | 34 | |
71ccdfff | 35 | #ifdef HAVE_STRING_H |
36 | #include <string.h> | |
71ccdfff | 37 | #endif |
38 | #ifdef HAVE_STDLIB_H | |
39 | #include <stdlib.h> | |
40 | #else | |
11682839 | 41 | extern char * getenv (); |
71ccdfff | 42 | #endif |
e7a26f1b | 43 | |
ad87de1e | 44 | #ifdef NEED_DECLARATION_RINDEX |
e7a26f1b | 45 | extern char *rindex (); |
07d2156d | 46 | #endif |
e7a26f1b | 47 | extern char *getpwd PROTO((void)); |
71ccdfff | 48 | |
49 | static tree repo_get_id PROTO((tree)); | |
50 | static char *save_string PROTO((char *, int)); | |
51 | static char *extract_string PROTO((char **)); | |
52 | static char *get_base_filename PROTO((char *)); | |
53 | static void open_repo_file PROTO((char *)); | |
54 | static char *afgets PROTO((FILE *)); | |
55 | static void reopen_repo_file_for_write PROTO((void)); | |
bb09dca5 | 56 | |
57 | static tree pending_repo; | |
3e1ffd94 | 58 | static tree original_repo; |
3f7d79e4 | 59 | static char *repo_name; |
bb09dca5 | 60 | static FILE *repo_file; |
61 | ||
6686e84d | 62 | static char *old_args, *old_dir, *old_main; |
63 | ||
bb09dca5 | 64 | extern int flag_use_repository; |
65 | extern int errorcount, sorrycount; | |
3f7d79e4 | 66 | extern struct obstack temporary_obstack; |
67 | extern struct obstack permanent_obstack; | |
bb09dca5 | 68 | |
bb09dca5 | 69 | #define IDENTIFIER_REPO_USED(NODE) (TREE_LANG_FLAG_3 (NODE)) |
70 | #define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE)) | |
71 | ||
e857e9c7 | 72 | #if 0 |
bb09dca5 | 73 | /* Record the flags used to compile this translation unit. */ |
74 | ||
75 | void | |
76 | repo_compile_flags (argc, argv) | |
77 | int argc; | |
78 | char **argv; | |
79 | { | |
80 | } | |
81 | ||
82 | /* If this template has not been seen before, add a note to the repository | |
83 | saying where the declaration was. This may be used to find the | |
84 | definition at link time. */ | |
85 | ||
86 | void | |
87 | repo_template_declared (t) | |
88 | tree t; | |
89 | {} | |
90 | ||
91 | /* Note where the definition of a template lives so that instantiations can | |
92 | be generated later. */ | |
93 | ||
94 | void | |
95 | repo_template_defined (t) | |
96 | tree t; | |
97 | {} | |
98 | ||
99 | /* Note where the definition of a class lives to that template | |
100 | instantiations can use it. */ | |
101 | ||
102 | void | |
103 | repo_class_defined (t) | |
104 | tree t; | |
105 | {} | |
e857e9c7 | 106 | #endif |
bb09dca5 | 107 | |
e857e9c7 | 108 | static tree |
dc76caae | 109 | repo_get_id (t) |
110 | tree t; | |
111 | { | |
112 | if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') | |
113 | { | |
114 | t = TYPE_BINFO_VTABLE (t); | |
115 | if (t == NULL_TREE) | |
116 | return t; | |
117 | } | |
118 | return DECL_ASSEMBLER_NAME (t); | |
119 | } | |
120 | ||
bb09dca5 | 121 | /* Note that a template has been used. If we can see the definition, offer |
96624a9e | 122 | to emit it. */ |
bb09dca5 | 123 | |
124 | void | |
125 | repo_template_used (t) | |
126 | tree t; | |
127 | { | |
128 | tree id; | |
129 | ||
130 | if (! flag_use_repository) | |
131 | return; | |
132 | ||
dc76caae | 133 | id = repo_get_id (t); |
134 | if (id == NULL_TREE) | |
135 | return; | |
136 | ||
bb09dca5 | 137 | if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') |
138 | { | |
bb09dca5 | 139 | if (IDENTIFIER_REPO_CHOSEN (id)) |
140 | mark_class_instantiated (t, 0); | |
141 | } | |
142 | else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd') | |
143 | { | |
bb09dca5 | 144 | if (IDENTIFIER_REPO_CHOSEN (id)) |
e857e9c7 | 145 | mark_decl_instantiated (t, 0); |
bb09dca5 | 146 | } |
147 | else | |
148 | my_friendly_abort (1); | |
149 | ||
150 | if (! IDENTIFIER_REPO_USED (id)) | |
151 | { | |
bb09dca5 | 152 | IDENTIFIER_REPO_USED (id) = 1; |
3e1ffd94 | 153 | pending_repo = perm_tree_cons (NULL_TREE, id, pending_repo); |
bb09dca5 | 154 | } |
bb09dca5 | 155 | } |
156 | ||
e857e9c7 | 157 | #if 0 |
bb09dca5 | 158 | /* Note that the vtable for a class has been used, and offer to emit it. */ |
159 | ||
e857e9c7 | 160 | static void |
bb09dca5 | 161 | repo_vtable_used (t) |
162 | tree t; | |
163 | { | |
164 | if (! flag_use_repository) | |
165 | return; | |
166 | ||
167 | pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo); | |
168 | } | |
169 | ||
170 | /* Note that an inline with external linkage has been used, and offer to | |
171 | emit it. */ | |
172 | ||
173 | void | |
174 | repo_inline_used (fn) | |
175 | tree fn; | |
176 | { | |
177 | if (! flag_use_repository) | |
178 | return; | |
179 | ||
180 | /* Member functions of polymorphic classes go with their vtables. */ | |
181 | if (DECL_FUNCTION_MEMBER_P (fn) && TYPE_VIRTUAL_P (DECL_CLASS_CONTEXT (fn))) | |
182 | { | |
183 | repo_vtable_used (DECL_CLASS_CONTEXT (fn)); | |
184 | return; | |
185 | } | |
186 | ||
187 | pending_repo = perm_tree_cons (NULL_TREE, fn, pending_repo); | |
188 | } | |
189 | ||
190 | /* Note that a particular typeinfo node has been used, and offer to | |
191 | emit it. */ | |
192 | ||
193 | void | |
194 | repo_tinfo_used (ti) | |
195 | tree ti; | |
196 | { | |
197 | } | |
e857e9c7 | 198 | #endif |
bb09dca5 | 199 | |
dc76caae | 200 | void |
201 | repo_template_instantiated (t, extern_p) | |
202 | tree t; | |
203 | int extern_p; | |
204 | { | |
205 | if (! extern_p) | |
206 | { | |
207 | tree id = repo_get_id (t); | |
208 | if (id) | |
209 | IDENTIFIER_REPO_CHOSEN (id) = 1; | |
210 | } | |
211 | } | |
212 | ||
11682839 | 213 | static char * |
214 | save_string (s, len) | |
215 | char *s; | |
216 | int len; | |
217 | { | |
3e1ffd94 | 218 | return obstack_copy0 (&temporary_obstack, s, len); |
11682839 | 219 | } |
220 | ||
6686e84d | 221 | /* Parse a reasonable subset of shell quoting syntax. */ |
222 | ||
223 | static char * | |
224 | extract_string (pp) | |
225 | char **pp; | |
226 | { | |
227 | char *p = *pp; | |
228 | int backquote = 0; | |
229 | int inside = 0; | |
230 | ||
231 | for (;;) | |
232 | { | |
233 | char c = *p; | |
234 | if (c == '\0') | |
235 | break; | |
236 | ++p; | |
237 | if (backquote) | |
238 | obstack_1grow (&temporary_obstack, c); | |
239 | else if (! inside && c == ' ') | |
240 | break; | |
241 | else if (! inside && c == '\\') | |
242 | backquote = 1; | |
243 | else if (c == '\'') | |
244 | inside = !inside; | |
245 | else | |
246 | obstack_1grow (&temporary_obstack, c); | |
247 | } | |
248 | ||
249 | obstack_1grow (&temporary_obstack, '\0'); | |
250 | *pp = p; | |
251 | return obstack_finish (&temporary_obstack); | |
252 | } | |
253 | ||
11682839 | 254 | static char * |
255 | get_base_filename (filename) | |
256 | char *filename; | |
257 | { | |
258 | char *p = getenv ("COLLECT_GCC_OPTIONS"); | |
6686e84d | 259 | char *output = NULL; |
11682839 | 260 | int compiling = 0; |
261 | ||
6686e84d | 262 | while (p && *p) |
263 | { | |
264 | char *q = extract_string (&p); | |
11682839 | 265 | |
6686e84d | 266 | if (strcmp (q, "-o") == 0) |
267 | output = extract_string (&p); | |
268 | else if (strcmp (q, "-c") == 0) | |
269 | compiling = 1; | |
11682839 | 270 | } |
271 | ||
272 | if (compiling && output) | |
273 | return output; | |
274 | ||
3e1ffd94 | 275 | if (p && ! compiling) |
276 | { | |
277 | warning ("-frepo must be used with -c"); | |
278 | flag_use_repository = 0; | |
279 | return NULL; | |
280 | } | |
281 | ||
e7a26f1b | 282 | p = rindex (filename, '/'); |
3e1ffd94 | 283 | if (p) |
284 | return p+1; | |
285 | else | |
286 | return filename; | |
11682839 | 287 | } |
288 | ||
bb09dca5 | 289 | static void |
290 | open_repo_file (filename) | |
291 | char *filename; | |
292 | { | |
e857e9c7 | 293 | register char *p; |
3f7d79e4 | 294 | char *s = get_base_filename (filename); |
3e1ffd94 | 295 | |
3f7d79e4 | 296 | if (s == NULL) |
3e1ffd94 | 297 | return; |
298 | ||
e7a26f1b | 299 | p = rindex (s, '/'); |
3f7d79e4 | 300 | if (! p) |
301 | p = s; | |
e7a26f1b | 302 | p = rindex (p, '.'); |
3f7d79e4 | 303 | if (! p) |
304 | p = s + strlen (s); | |
bb09dca5 | 305 | |
3f7d79e4 | 306 | obstack_grow (&permanent_obstack, s, p - s); |
307 | repo_name = obstack_copy0 (&permanent_obstack, ".rpo", 4); | |
bb09dca5 | 308 | |
309 | repo_file = fopen (repo_name, "r"); | |
310 | } | |
311 | ||
3f7d79e4 | 312 | static char * |
313 | afgets (stream) | |
314 | FILE *stream; | |
315 | { | |
316 | int c; | |
317 | while ((c = getc (stream)) != EOF && c != '\n') | |
318 | obstack_1grow (&temporary_obstack, c); | |
319 | if (obstack_object_size (&temporary_obstack) == 0) | |
320 | return NULL; | |
321 | obstack_1grow (&temporary_obstack, '\0'); | |
322 | return obstack_finish (&temporary_obstack); | |
323 | } | |
324 | ||
bb09dca5 | 325 | void |
326 | init_repo (filename) | |
327 | char *filename; | |
328 | { | |
3f7d79e4 | 329 | char *buf; |
bb09dca5 | 330 | |
331 | if (! flag_use_repository) | |
332 | return; | |
333 | ||
3e1ffd94 | 334 | open_repo_file (filename); |
bb09dca5 | 335 | |
336 | if (repo_file == 0) | |
337 | return; | |
338 | ||
034b484a | 339 | while ((buf = afgets (repo_file))) |
bb09dca5 | 340 | { |
bb09dca5 | 341 | switch (buf[0]) |
342 | { | |
343 | case 'A': | |
6686e84d | 344 | old_args = obstack_copy0 (&permanent_obstack, buf + 2, |
345 | strlen (buf + 2)); | |
346 | break; | |
3f7d79e4 | 347 | case 'D': |
6686e84d | 348 | old_dir = obstack_copy0 (&permanent_obstack, buf + 2, |
349 | strlen (buf + 2)); | |
350 | break; | |
bb09dca5 | 351 | case 'M': |
6686e84d | 352 | old_main = obstack_copy0 (&permanent_obstack, buf + 2, |
353 | strlen (buf + 2)); | |
bb09dca5 | 354 | break; |
355 | case 'C': | |
356 | case 'O': | |
357 | { | |
3f7d79e4 | 358 | tree id = get_identifier (buf + 2); |
359 | tree orig; | |
3e1ffd94 | 360 | |
bb09dca5 | 361 | if (buf[0] == 'C') |
dc76caae | 362 | { |
363 | IDENTIFIER_REPO_CHOSEN (id) = 1; | |
364 | orig = integer_one_node; | |
365 | } | |
366 | else | |
367 | orig = NULL_TREE; | |
368 | ||
369 | original_repo = perm_tree_cons (orig, id, original_repo); | |
bb09dca5 | 370 | } |
371 | break; | |
372 | default: | |
373 | error ("mysterious repository information in %s", repo_name); | |
374 | } | |
3f7d79e4 | 375 | obstack_free (&temporary_obstack, buf); |
bb09dca5 | 376 | } |
377 | } | |
378 | ||
379 | static void | |
380 | reopen_repo_file_for_write () | |
381 | { | |
382 | if (repo_file) | |
383 | fclose (repo_file); | |
384 | repo_file = fopen (repo_name, "w"); | |
385 | ||
386 | if (repo_file == 0) | |
387 | { | |
11682839 | 388 | error ("can't create repository information file `%s'", repo_name); |
bb09dca5 | 389 | flag_use_repository = 0; |
390 | } | |
391 | } | |
392 | ||
393 | /* Emit any pending repos. */ | |
394 | ||
395 | void | |
396 | finish_repo () | |
397 | { | |
398 | tree t; | |
3e1ffd94 | 399 | int repo_changed = 0; |
6686e84d | 400 | char *dir, *args; |
bb09dca5 | 401 | |
402 | if (! flag_use_repository) | |
403 | return; | |
404 | ||
405 | /* Do we have to write out a new info file? */ | |
406 | ||
dc76caae | 407 | /* Are there any old templates that aren't used any longer or that are |
408 | newly chosen? */ | |
3e1ffd94 | 409 | |
410 | for (t = original_repo; t; t = TREE_CHAIN (t)) | |
411 | { | |
dc76caae | 412 | if (! IDENTIFIER_REPO_USED (TREE_VALUE (t)) |
413 | || (! TREE_PURPOSE (t) && IDENTIFIER_REPO_CHOSEN (TREE_VALUE (t)))) | |
3e1ffd94 | 414 | { |
415 | repo_changed = 1; | |
416 | break; | |
417 | } | |
418 | IDENTIFIER_REPO_USED (TREE_VALUE (t)) = 0; | |
419 | } | |
420 | ||
421 | /* Are there any templates that are newly used? */ | |
422 | ||
423 | if (! repo_changed) | |
424 | for (t = pending_repo; t; t = TREE_CHAIN (t)) | |
425 | { | |
426 | if (IDENTIFIER_REPO_USED (TREE_VALUE (t))) | |
427 | { | |
428 | repo_changed = 1; | |
429 | break; | |
430 | } | |
431 | } | |
432 | ||
6686e84d | 433 | dir = getpwd (); |
434 | args = getenv ("COLLECT_GCC_OPTIONS"); | |
435 | ||
436 | if (! repo_changed && pending_repo) | |
437 | if (strcmp (old_main, main_input_filename) != 0 | |
438 | || strcmp (old_dir, dir) != 0 | |
439 | || (args == NULL) != (old_args == NULL) | |
c90e0199 | 440 | || (args && strcmp (old_args, args) != 0)) |
6686e84d | 441 | repo_changed = 1; |
442 | ||
bb09dca5 | 443 | if (! repo_changed || errorcount || sorrycount) |
444 | goto out; | |
445 | ||
446 | reopen_repo_file_for_write (); | |
447 | ||
448 | if (repo_file == 0) | |
449 | goto out; | |
450 | ||
11682839 | 451 | fprintf (repo_file, "M %s\n", main_input_filename); |
6686e84d | 452 | fprintf (repo_file, "D %s\n", dir); |
453 | if (args) | |
454 | fprintf (repo_file, "A %s\n", args); | |
11682839 | 455 | |
bb09dca5 | 456 | for (t = pending_repo; t; t = TREE_CHAIN (t)) |
457 | { | |
458 | tree val = TREE_VALUE (t); | |
3e1ffd94 | 459 | char type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O'; |
bb09dca5 | 460 | |
3f7d79e4 | 461 | fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val)); |
bb09dca5 | 462 | } |
463 | ||
464 | out: | |
465 | if (repo_file) | |
466 | fclose (repo_file); | |
467 | } |