re PR middle-end/42834 (memcpy folding overeager)
[gcc.git] / gcc / c-family / c-ada-spec.c
1 /* Print GENERIC declaration (functions, variables, types) trees coming from
2 the C and C++ front-ends as well as macros in Ada syntax.
3 Copyright (C) 2010 Free Software Foundation, Inc.
4 Adapted from tree-pretty-print.c by Arnaud Charlet <charlet@adacore.com>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "tree-pass.h" /* For TDI_ada and friends. */
28 #include "output.h"
29 #include "c-ada-spec.h"
30 #include "cpplib.h"
31 #include "c-pragma.h"
32 #include "cpp-id-data.h"
33
34 /* Local functions, macros and variables. */
35 static int dump_generic_ada_node (pretty_printer *, tree, tree,
36 int (*)(tree, cpp_operation), int, int, bool);
37 static int print_ada_declaration (pretty_printer *, tree, tree,
38 int (*cpp_check)(tree, cpp_operation), int);
39 static void print_ada_struct_decl (pretty_printer *, tree, tree,
40 int (*cpp_check)(tree, cpp_operation), int,
41 bool);
42 static void dump_sloc (pretty_printer *buffer, tree node);
43 static void print_comment (pretty_printer *, const char *);
44 static void print_generic_ada_decl (pretty_printer *, tree,
45 int (*)(tree, cpp_operation), const char *);
46 static char *get_ada_package (const char *);
47 static void dump_ada_nodes (pretty_printer *, const char *,
48 int (*)(tree, cpp_operation));
49 static void reset_ada_withs (void);
50 static void dump_ada_withs (FILE *);
51 static void dump_ads (const char *, void (*)(const char *),
52 int (*)(tree, cpp_operation));
53 static char *to_ada_name (const char *, int *);
54
55 #define LOCATION_COL(LOC) ((expand_location (LOC)).column)
56
57 #define INDENT(SPACE) do { \
58 int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
59
60 #define INDENT_INCR 3
61
62 /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
63 as max length PARAM_LEN of arguments for fun_like macros, and also set
64 SUPPORTED to 0 if the macro cannot be mapped to an Ada construct. */
65
66 static void
67 macro_length (const cpp_macro *macro, int *supported, int *buffer_len,
68 int *param_len)
69 {
70 int i;
71 unsigned j;
72
73 *supported = 1;
74 *buffer_len = 0;
75 *param_len = 0;
76
77 if (macro->fun_like)
78 {
79 param_len++;
80 for (i = 0; i < macro->paramc; i++)
81 {
82 cpp_hashnode *param = macro->params[i];
83
84 *param_len += NODE_LEN (param);
85
86 if (i + 1 < macro->paramc)
87 {
88 *param_len += 2; /* ", " */
89 }
90 else if (macro->variadic)
91 {
92 *supported = 0;
93 return;
94 }
95 }
96 *param_len += 2; /* ")\0" */
97 }
98
99 for (j = 0; j < macro->count; j++)
100 {
101 cpp_token *token = &macro->exp.tokens[j];
102
103 if (token->flags & PREV_WHITE)
104 (*buffer_len)++;
105
106 if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
107 {
108 *supported = 0;
109 return;
110 }
111
112 if (token->type == CPP_MACRO_ARG)
113 *buffer_len +=
114 NODE_LEN (macro->params[token->val.macro_arg.arg_no - 1]);
115 else
116 /* Include enough extra space to handle e.g. special characters. */
117 *buffer_len += (cpp_token_len (token) + 1) * 8;
118 }
119
120 (*buffer_len)++;
121 }
122
123 /* Dump into PP a set of MAX_ADA_MACROS MACROS (C/C++) as Ada constants when
124 possible. */
125
126 static void
127 print_ada_macros (pretty_printer *pp, cpp_hashnode **macros, int max_ada_macros)
128 {
129 int j, num_macros = 0, prev_line = -1;
130
131 for (j = 0; j < max_ada_macros; j++)
132 {
133 cpp_hashnode *node = macros [j];
134 const cpp_macro *macro = node->value.macro;
135 unsigned i;
136 int supported = 1, prev_is_one = 0, buffer_len, param_len;
137 int is_string = 0, is_char = 0;
138 char *ada_name;
139 unsigned char *s, *params, *buffer, *buf_param, *char_one = NULL;
140
141 macro_length (macro, &supported, &buffer_len, &param_len);
142 s = buffer = XALLOCAVEC (unsigned char, buffer_len);
143 params = buf_param = XALLOCAVEC (unsigned char, param_len);
144
145 if (supported)
146 {
147 if (macro->fun_like)
148 {
149 *buf_param++ = '(';
150 for (i = 0; i < macro->paramc; i++)
151 {
152 cpp_hashnode *param = macro->params[i];
153
154 memcpy (buf_param, NODE_NAME (param), NODE_LEN (param));
155 buf_param += NODE_LEN (param);
156
157 if (i + 1 < macro->paramc)
158 {
159 *buf_param++ = ',';
160 *buf_param++ = ' ';
161 }
162 else if (macro->variadic)
163 {
164 supported = 0;
165 break;
166 }
167 }
168 *buf_param++ = ')';
169 *buf_param = '\0';
170 }
171
172 for (i = 0; supported && i < macro->count; i++)
173 {
174 cpp_token *token = &macro->exp.tokens[i];
175 int is_one = 0;
176
177 if (token->flags & PREV_WHITE)
178 *buffer++ = ' ';
179
180 if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
181 {
182 supported = 0;
183 break;
184 }
185
186 switch (token->type)
187 {
188 case CPP_MACRO_ARG:
189 {
190 cpp_hashnode *param =
191 macro->params[token->val.macro_arg.arg_no - 1];
192 memcpy (buffer, NODE_NAME (param), NODE_LEN (param));
193 buffer += NODE_LEN (param);
194 }
195 break;
196
197 case CPP_EQ_EQ: *buffer++ = '='; break;
198 case CPP_GREATER: *buffer++ = '>'; break;
199 case CPP_LESS: *buffer++ = '<'; break;
200 case CPP_PLUS: *buffer++ = '+'; break;
201 case CPP_MINUS: *buffer++ = '-'; break;
202 case CPP_MULT: *buffer++ = '*'; break;
203 case CPP_DIV: *buffer++ = '/'; break;
204 case CPP_COMMA: *buffer++ = ','; break;
205 case CPP_OPEN_SQUARE:
206 case CPP_OPEN_PAREN: *buffer++ = '('; break;
207 case CPP_CLOSE_SQUARE: /* fallthrough */
208 case CPP_CLOSE_PAREN: *buffer++ = ')'; break;
209 case CPP_DEREF: /* fallthrough */
210 case CPP_SCOPE: /* fallthrough */
211 case CPP_DOT: *buffer++ = '.'; break;
212
213 case CPP_EQ: *buffer++ = ':'; *buffer++ = '='; break;
214 case CPP_NOT_EQ: *buffer++ = '/'; *buffer++ = '='; break;
215 case CPP_GREATER_EQ: *buffer++ = '>'; *buffer++ = '='; break;
216 case CPP_LESS_EQ: *buffer++ = '<'; *buffer++ = '='; break;
217
218 case CPP_NOT:
219 *buffer++ = 'n'; *buffer++ = 'o'; *buffer++ = 't'; break;
220 case CPP_MOD:
221 *buffer++ = 'm'; *buffer++ = 'o'; *buffer++ = 'd'; break;
222 case CPP_AND:
223 *buffer++ = 'a'; *buffer++ = 'n'; *buffer++ = 'd'; break;
224 case CPP_OR:
225 *buffer++ = 'o'; *buffer++ = 'r'; break;
226 case CPP_XOR:
227 *buffer++ = 'x'; *buffer++ = 'o'; *buffer++ = 'r'; break;
228 case CPP_AND_AND:
229 strcpy ((char *) buffer, " and then ");
230 buffer += 10;
231 break;
232 case CPP_OR_OR:
233 strcpy ((char *) buffer, " or else ");
234 buffer += 9;
235 break;
236
237 case CPP_PADDING:
238 *buffer++ = ' ';
239 is_one = prev_is_one;
240 break;
241
242 case CPP_COMMENT: break;
243
244 case CPP_WSTRING:
245 case CPP_STRING16:
246 case CPP_STRING32:
247 case CPP_UTF8STRING:
248 case CPP_WCHAR:
249 case CPP_CHAR16:
250 case CPP_CHAR32:
251 case CPP_NAME:
252 case CPP_STRING:
253 case CPP_NUMBER:
254 if (!macro->fun_like)
255 supported = 0;
256 else
257 buffer = cpp_spell_token (parse_in, token, buffer, false);
258 break;
259
260 case CPP_CHAR:
261 is_char = 1;
262 {
263 unsigned chars_seen;
264 int ignored;
265 cppchar_t c;
266
267 c = cpp_interpret_charconst (parse_in, token,
268 &chars_seen, &ignored);
269 if (c >= 32 && c <= 126)
270 {
271 *buffer++ = '\'';
272 *buffer++ = (char) c;
273 *buffer++ = '\'';
274 }
275 else
276 {
277 chars_seen = sprintf
278 ((char *) buffer, "Character'Val (%d)", (int) c);
279 buffer += chars_seen;
280 }
281 }
282 break;
283
284 case CPP_LSHIFT:
285 if (prev_is_one)
286 {
287 /* Replace "1 << N" by "2 ** N" */
288 *char_one = '2';
289 *buffer++ = '*';
290 *buffer++ = '*';
291 break;
292 }
293 /* fallthrough */
294
295 case CPP_RSHIFT:
296 case CPP_COMPL:
297 case CPP_QUERY:
298 case CPP_EOF:
299 case CPP_PLUS_EQ:
300 case CPP_MINUS_EQ:
301 case CPP_MULT_EQ:
302 case CPP_DIV_EQ:
303 case CPP_MOD_EQ:
304 case CPP_AND_EQ:
305 case CPP_OR_EQ:
306 case CPP_XOR_EQ:
307 case CPP_RSHIFT_EQ:
308 case CPP_LSHIFT_EQ:
309 case CPP_PRAGMA:
310 case CPP_PRAGMA_EOL:
311 case CPP_HASH:
312 case CPP_PASTE:
313 case CPP_OPEN_BRACE:
314 case CPP_CLOSE_BRACE:
315 case CPP_SEMICOLON:
316 case CPP_ELLIPSIS:
317 case CPP_PLUS_PLUS:
318 case CPP_MINUS_MINUS:
319 case CPP_DEREF_STAR:
320 case CPP_DOT_STAR:
321 case CPP_ATSIGN:
322 case CPP_HEADER_NAME:
323 case CPP_AT_NAME:
324 case CPP_OTHER:
325 case CPP_OBJC_STRING:
326 default:
327 if (!macro->fun_like)
328 supported = 0;
329 else
330 buffer = cpp_spell_token (parse_in, token, buffer, false);
331 break;
332 }
333
334 prev_is_one = is_one;
335 }
336
337 if (supported)
338 *buffer = '\0';
339 }
340
341 if (macro->fun_like && supported)
342 {
343 char *start = (char *) s;
344 int is_function = 0;
345
346 pp_string (pp, " -- arg-macro: ");
347
348 if (*start == '(' && buffer [-1] == ')')
349 {
350 start++;
351 buffer [-1] = '\0';
352 is_function = 1;
353 pp_string (pp, "function ");
354 }
355 else
356 {
357 pp_string (pp, "procedure ");
358 }
359
360 pp_string (pp, (const char *) NODE_NAME (node));
361 pp_space (pp);
362 pp_string (pp, (char *) params);
363 pp_newline (pp);
364 pp_string (pp, " -- ");
365
366 if (is_function)
367 {
368 pp_string (pp, "return ");
369 pp_string (pp, start);
370 pp_semicolon (pp);
371 }
372 else
373 pp_string (pp, start);
374
375 pp_newline (pp);
376 }
377 else if (supported)
378 {
379 expanded_location sloc = expand_location (macro->line);
380
381 if (sloc.line != prev_line + 1)
382 pp_newline (pp);
383
384 num_macros++;
385 prev_line = sloc.line;
386
387 pp_string (pp, " ");
388 ada_name = to_ada_name ((const char *) NODE_NAME (node), NULL);
389 pp_string (pp, ada_name);
390 free (ada_name);
391 pp_string (pp, " : ");
392
393 if (is_string)
394 pp_string (pp, "aliased constant String");
395 else if (is_char)
396 pp_string (pp, "aliased constant Character");
397 else
398 pp_string (pp, "constant");
399
400 pp_string (pp, " := ");
401 pp_string (pp, (char *) s);
402
403 if (is_string)
404 pp_string (pp, " & ASCII.NUL");
405
406 pp_string (pp, "; -- ");
407 pp_string (pp, sloc.file);
408 pp_character (pp, ':');
409 pp_scalar (pp, "%d", sloc.line);
410 pp_newline (pp);
411 }
412 else
413 {
414 pp_string (pp, " -- unsupported macro: ");
415 pp_string (pp, (const char *) cpp_macro_definition (parse_in, node));
416 pp_newline (pp);
417 }
418 }
419
420 if (num_macros > 0)
421 pp_newline (pp);
422 }
423
424 static const char *source_file;
425 static int max_ada_macros;
426
427 /* Callback used to count the number of relevant macros from
428 cpp_forall_identifiers. PFILE and V are not used. NODE is the current macro
429 to consider. */
430
431 static int
432 count_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node,
433 void *v ATTRIBUTE_UNUSED)
434 {
435 const cpp_macro *macro = node->value.macro;
436
437 if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
438 && macro->count
439 && *NODE_NAME (node) != '_'
440 && LOCATION_FILE (macro->line) == source_file)
441 max_ada_macros++;
442
443 return 1;
444 }
445
446 static int store_ada_macro_index;
447
448 /* Callback used to store relevant macros from cpp_forall_identifiers.
449 PFILE is not used. NODE is the current macro to store if relevant.
450 MACROS is an array of cpp_hashnode* used to store NODE. */
451
452 static int
453 store_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED,
454 cpp_hashnode *node, void *macros)
455 {
456 const cpp_macro *macro = node->value.macro;
457
458 if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
459 && macro->count
460 && *NODE_NAME (node) != '_'
461 && LOCATION_FILE (macro->line) == source_file)
462 ((cpp_hashnode **) macros)[store_ada_macro_index++] = node;
463
464 return 1;
465 }
466
467 /* Callback used to compare (during qsort) macros. NODE1 and NODE2 are the
468 two macro nodes to compare. */
469
470 static int
471 compare_macro (const void *node1, const void *node2)
472 {
473 typedef const cpp_hashnode *const_hnode;
474
475 const_hnode n1 = *(const const_hnode *) node1;
476 const_hnode n2 = *(const const_hnode *) node2;
477
478 return n1->value.macro->line - n2->value.macro->line;
479 }
480
481 /* Dump in PP all relevant macros appearing in FILE. */
482
483 static void
484 dump_ada_macros (pretty_printer *pp, const char* file)
485 {
486 cpp_hashnode **macros;
487
488 /* Initialize file-scope variables. */
489 max_ada_macros = 0;
490 store_ada_macro_index = 0;
491 source_file = file;
492
493 /* Count all potentially relevant macros, and then sort them by sloc. */
494 cpp_forall_identifiers (parse_in, count_ada_macro, NULL);
495 macros = XALLOCAVEC (cpp_hashnode *, max_ada_macros);
496 cpp_forall_identifiers (parse_in, store_ada_macro, macros);
497 qsort (macros, max_ada_macros, sizeof (cpp_hashnode *), compare_macro);
498
499 print_ada_macros (pp, macros, max_ada_macros);
500 }
501
502 /* Current source file being handled. */
503
504 static const char *source_file_base;
505
506 /* Compare the declaration (DECL) of struct-like types based on the sloc of
507 their last field (if LAST is true), so that more nested types collate before
508 less nested ones.
509 If ORIG_TYPE is true, also consider struct with a DECL_ORIGINAL_TYPE. */
510
511 static location_t
512 decl_sloc_common (const_tree decl, bool last, bool orig_type)
513 {
514 tree type = TREE_TYPE (decl);
515
516 if (TREE_CODE (decl) == TYPE_DECL
517 && (orig_type || !DECL_ORIGINAL_TYPE (decl))
518 && RECORD_OR_UNION_TYPE_P (type)
519 && TYPE_FIELDS (type))
520 {
521 tree f = TYPE_FIELDS (type);
522
523 if (last)
524 while (TREE_CHAIN (f))
525 f = TREE_CHAIN (f);
526
527 return DECL_SOURCE_LOCATION (f);
528 }
529 else
530 return DECL_SOURCE_LOCATION (decl);
531 }
532
533 /* Return sloc of DECL, using sloc of last field if LAST is true. */
534
535 location_t
536 decl_sloc (const_tree decl, bool last)
537 {
538 return decl_sloc_common (decl, last, false);
539 }
540
541 /* Compare two declarations (LP and RP) by their source location. */
542
543 static int
544 compare_node (const void *lp, const void *rp)
545 {
546 const_tree lhs = *((const tree *) lp);
547 const_tree rhs = *((const tree *) rp);
548
549 return decl_sloc (lhs, true) - decl_sloc (rhs, true);
550 }
551
552 /* Compare two comments (LP and RP) by their source location. */
553
554 static int
555 compare_comment (const void *lp, const void *rp)
556 {
557 const cpp_comment *lhs = (const cpp_comment *) lp;
558 const cpp_comment *rhs = (const cpp_comment *) rp;
559
560 if (LOCATION_FILE (lhs->sloc) != LOCATION_FILE (rhs->sloc))
561 return strcmp (LOCATION_FILE (lhs->sloc), LOCATION_FILE (rhs->sloc));
562
563 if (LOCATION_LINE (lhs->sloc) != LOCATION_LINE (rhs->sloc))
564 return LOCATION_LINE (lhs->sloc) - LOCATION_LINE (rhs->sloc);
565
566 if (LOCATION_COL (lhs->sloc) != LOCATION_COL (rhs->sloc))
567 return LOCATION_COL (lhs->sloc) - LOCATION_COL (rhs->sloc);
568
569 return 0;
570 }
571
572 static tree *to_dump = NULL;
573 static int to_dump_count = 0;
574
575 /* Collect a list of declarations from T relevant to SOURCE_FILE to be dumped
576 by a subsequent call to dump_ada_nodes. */
577
578 void
579 collect_ada_nodes (tree t, const char *source_file)
580 {
581 tree n;
582 int i = to_dump_count;
583
584 /* Count the likely relevant nodes. */
585 for (n = t; n; n = TREE_CHAIN (n))
586 if (!DECL_IS_BUILTIN (n)
587 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
588 to_dump_count++;
589
590 /* Allocate sufficient storage for all nodes. */
591 to_dump = XRESIZEVEC (tree, to_dump, to_dump_count);
592
593 /* Store the relevant nodes. */
594 for (n = t; n; n = TREE_CHAIN (n))
595 if (!DECL_IS_BUILTIN (n)
596 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
597 to_dump [i++] = n;
598 }
599
600 /* Call back for walk_tree to clear the TREE_VISITED flag of TP. */
601
602 static tree
603 unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
604 void *data ATTRIBUTE_UNUSED)
605 {
606 if (TREE_VISITED (*tp))
607 TREE_VISITED (*tp) = 0;
608 else
609 *walk_subtrees = 0;
610
611 return NULL_TREE;
612 }
613
614 /* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
615 to collect_ada_nodes. CPP_CHECK is used to perform C++ queries on nodes. */
616
617 static void
618 dump_ada_nodes (pretty_printer *pp, const char *source_file,
619 int (*cpp_check)(tree, cpp_operation))
620 {
621 int i, j;
622 cpp_comment_table *comments;
623
624 /* Sort the table of declarations to dump by sloc. */
625 qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
626
627 /* Fetch the table of comments. */
628 comments = cpp_get_comments (parse_in);
629
630 /* Sort the comments table by sloc. */
631 qsort (comments->entries, comments->count, sizeof (cpp_comment),
632 compare_comment);
633
634 /* Interleave comments and declarations in line number order. */
635 i = j = 0;
636 do
637 {
638 /* Advance j until comment j is in this file. */
639 while (j != comments->count
640 && LOCATION_FILE (comments->entries[j].sloc) != source_file)
641 j++;
642
643 /* Advance j until comment j is not a duplicate. */
644 while (j < comments->count - 1
645 && !compare_comment (&comments->entries[j],
646 &comments->entries[j + 1]))
647 j++;
648
649 /* Write decls until decl i collates after comment j. */
650 while (i != to_dump_count)
651 {
652 if (j == comments->count
653 || LOCATION_LINE (decl_sloc (to_dump[i], false))
654 < LOCATION_LINE (comments->entries[j].sloc))
655 print_generic_ada_decl (pp, to_dump[i++], cpp_check, source_file);
656 else
657 break;
658 }
659
660 /* Write comment j, if there is one. */
661 if (j != comments->count)
662 print_comment (pp, comments->entries[j++].comment);
663
664 } while (i != to_dump_count || j != comments->count);
665
666 /* Clear the TREE_VISITED flag over each subtree we've dumped. */
667 for (i = 0; i < to_dump_count; i++)
668 walk_tree (&to_dump[i], unmark_visited_r, NULL, NULL);
669
670 /* Finalize the to_dump table. */
671 if (to_dump)
672 {
673 free (to_dump);
674 to_dump = NULL;
675 to_dump_count = 0;
676 }
677 }
678
679 /* Print a COMMENT to the output stream PP. */
680
681 static void
682 print_comment (pretty_printer *pp, const char *comment)
683 {
684 int len = strlen (comment);
685 char *str = XALLOCAVEC (char, len + 1);
686 char *tok;
687 bool extra_newline = false;
688
689 memcpy (str, comment, len + 1);
690
691 /* Trim C/C++ comment indicators. */
692 if (str[len - 2] == '*' && str[len - 1] == '/')
693 {
694 str[len - 2] = ' ';
695 str[len - 1] = '\0';
696 }
697 str += 2;
698
699 tok = strtok (str, "\n");
700 while (tok) {
701 pp_string (pp, " --");
702 pp_string (pp, tok);
703 pp_newline (pp);
704 tok = strtok (NULL, "\n");
705
706 /* Leave a blank line after multi-line comments. */
707 if (tok)
708 extra_newline = true;
709 }
710
711 if (extra_newline)
712 pp_newline (pp);
713 }
714
715 /* Prints declaration DECL to PP in Ada syntax. The current source file being
716 handled is SOURCE_FILE, and CPP_CHECK is used to perform C++ queries on
717 nodes. */
718
719 static void
720 print_generic_ada_decl (pretty_printer *pp, tree decl,
721 int (*cpp_check)(tree, cpp_operation),
722 const char* source_file)
723 {
724 source_file_base = source_file;
725
726 if (print_ada_declaration (pp, decl, 0, cpp_check, INDENT_INCR))
727 {
728 pp_newline (pp);
729 pp_newline (pp);
730 }
731 }
732
733 /* Dump a newline and indent BUFFER by SPC chars. */
734
735 static void
736 newline_and_indent (pretty_printer *buffer, int spc)
737 {
738 pp_newline (buffer);
739 INDENT (spc);
740 }
741
742 struct with { char *s; const char *in_file; int limited; };
743 static struct with *withs = NULL;
744 static int withs_max = 4096;
745 static int with_len = 0;
746
747 /* Record a "with" clause on package S (a limited with if LIMITED_ACCESS is
748 true), if not already done. */
749
750 static void
751 append_withs (const char *s, int limited_access)
752 {
753 int i;
754
755 if (withs == NULL)
756 withs = XNEWVEC (struct with, withs_max);
757
758 if (with_len == withs_max)
759 {
760 withs_max *= 2;
761 withs = XRESIZEVEC (struct with, withs, withs_max);
762 }
763
764 for (i = 0; i < with_len; i++)
765 if (!strcmp (s, withs [i].s)
766 && source_file_base == withs [i].in_file)
767 {
768 withs [i].limited &= limited_access;
769 return;
770 }
771
772 withs [with_len].s = xstrdup (s);
773 withs [with_len].in_file = source_file_base;
774 withs [with_len].limited = limited_access;
775 with_len++;
776 }
777
778 /* Reset "with" clauses. */
779
780 static void
781 reset_ada_withs (void)
782 {
783 int i;
784
785 if (!withs)
786 return;
787
788 for (i = 0; i < with_len; i++)
789 free (withs [i].s);
790 free (withs);
791 withs = NULL;
792 withs_max = 4096;
793 with_len = 0;
794 }
795
796 /* Dump "with" clauses in F. */
797
798 static void
799 dump_ada_withs (FILE *f)
800 {
801 int i;
802
803 fprintf (f, "with Interfaces.C; use Interfaces.C;\n");
804
805 for (i = 0; i < with_len; i++)
806 fprintf
807 (f, "%swith %s;\n", withs [i].limited ? "limited " : "", withs [i].s);
808 }
809
810 /* Return suitable Ada package name from FILE. */
811
812 static char *
813 get_ada_package (const char *file)
814 {
815 const char *base;
816 char *res;
817 const char *s;
818 int i;
819
820 s = strstr (file, "/include/");
821 if (s)
822 base = s + 9;
823 else
824 base = lbasename (file);
825 res = XNEWVEC (char, strlen (base) + 1);
826
827 for (i = 0; *base; base++, i++)
828 switch (*base)
829 {
830 case '+':
831 res [i] = 'p';
832 break;
833
834 case '.':
835 case '-':
836 case '_':
837 case '/':
838 case '\\':
839 res [i] = (i == 0 || res [i - 1] == '_') ? 'u' : '_';
840 break;
841
842 default:
843 res [i] = *base;
844 break;
845 }
846 res [i] = '\0';
847
848 return res;
849 }
850
851 static const char *ada_reserved[] = {
852 "abort", "abs", "abstract", "accept", "access", "aliased", "all", "and",
853 "array", "at", "begin", "body", "case", "constant", "declare", "delay",
854 "delta", "digits", "do", "else", "elsif", "end", "entry", "exception",
855 "exit", "for", "function", "generic", "goto", "if", "in", "interface", "is",
856 "limited", "loop", "mod", "new", "not", "null", "others", "out", "of", "or",
857 "overriding", "package", "pragma", "private", "procedure", "protected",
858 "raise", "range", "record", "rem", "renames", "requeue", "return", "reverse",
859 "select", "separate", "subtype", "synchronized", "tagged", "task",
860 "terminate", "then", "type", "until", "use", "when", "while", "with", "xor",
861 NULL};
862
863 /* ??? would be nice to specify this list via a config file, so that users
864 can create their own dictionary of conflicts. */
865 static const char *c_duplicates[] = {
866 /* system will cause troubles with System.Address. */
867 "system",
868
869 /* The following values have other definitions with same name/other
870 casing. */
871 "funmap",
872 "rl_vi_fWord",
873 "rl_vi_bWord",
874 "rl_vi_eWord",
875 "rl_readline_version",
876 "_Vx_ushort",
877 "USHORT",
878 "XLookupKeysym",
879 NULL};
880
881 /* Return a declaration tree corresponding to TYPE. */
882
883 static tree
884 get_underlying_decl (tree type)
885 {
886 tree decl = NULL_TREE;
887
888 if (type == NULL_TREE)
889 return NULL_TREE;
890
891 /* type is a declaration. */
892 if (DECL_P (type))
893 decl = type;
894
895 /* type is a typedef. */
896 if (TYPE_P (type) && TYPE_NAME (type) && DECL_P (TYPE_NAME (type)))
897 decl = TYPE_NAME (type);
898
899 /* TYPE_STUB_DECL has been set for type. */
900 if (TYPE_P (type) && TYPE_STUB_DECL (type) &&
901 DECL_P (TYPE_STUB_DECL (type)))
902 decl = TYPE_STUB_DECL (type);
903
904 return decl;
905 }
906
907 /* Return whether TYPE has static fields. */
908
909 static int
910 has_static_fields (const_tree type)
911 {
912 tree tmp;
913
914 for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
915 {
916 if (DECL_NAME (tmp) && TREE_STATIC (tmp))
917 return true;
918 }
919 return false;
920 }
921
922 /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
923 table). */
924
925 static int
926 is_tagged_type (const_tree type)
927 {
928 tree tmp;
929
930 if (!type || !RECORD_OR_UNION_TYPE_P (type))
931 return false;
932
933 for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
934 if (DECL_VINDEX (tmp))
935 return true;
936
937 return false;
938 }
939
940 /* Generate a legal Ada name from a C NAME, returning a malloc'd string.
941 SPACE_FOUND, if not NULL, is used to indicate whether a space was found in
942 NAME. */
943
944 static char *
945 to_ada_name (const char *name, int *space_found)
946 {
947 const char **names;
948 int len = strlen (name);
949 int j, len2 = 0;
950 int found = false;
951 char *s = XNEWVEC (char, len * 2 + 5);
952 char c;
953
954 if (space_found)
955 *space_found = false;
956
957 /* Add trailing "c_" if name is an Ada reserved word. */
958 for (names = ada_reserved; *names; names++)
959 if (!strcasecmp (name, *names))
960 {
961 s [len2++] = 'c';
962 s [len2++] = '_';
963 found = true;
964 break;
965 }
966
967 if (!found)
968 /* Add trailing "c_" if name is an potential case sensitive duplicate. */
969 for (names = c_duplicates; *names; names++)
970 if (!strcmp (name, *names))
971 {
972 s [len2++] = 'c';
973 s [len2++] = '_';
974 found = true;
975 break;
976 }
977
978 for (j = 0; name [j] == '_'; j++)
979 s [len2++] = 'u';
980
981 if (j > 0)
982 s [len2++] = '_';
983 else if (*name == '.' || *name == '$')
984 {
985 s [0] = 'a';
986 s [1] = 'n';
987 s [2] = 'o';
988 s [3] = 'n';
989 len2 = 4;
990 j++;
991 }
992
993 /* Replace unsuitable characters for Ada identifiers. */
994
995 for (; j < len; j++)
996 switch (name [j])
997 {
998 case ' ':
999 if (space_found)
1000 *space_found = true;
1001 s [len2++] = '_';
1002 break;
1003
1004 /* ??? missing some C++ operators. */
1005 case '=':
1006 s [len2++] = '_';
1007
1008 if (name [j + 1] == '=')
1009 {
1010 j++;
1011 s [len2++] = 'e';
1012 s [len2++] = 'q';
1013 }
1014 else
1015 {
1016 s [len2++] = 'a';
1017 s [len2++] = 's';
1018 }
1019 break;
1020
1021 case '!':
1022 s [len2++] = '_';
1023 if (name [j + 1] == '=')
1024 {
1025 j++;
1026 s [len2++] = 'n';
1027 s [len2++] = 'e';
1028 }
1029 break;
1030
1031 case '~':
1032 s [len2++] = '_';
1033 s [len2++] = 't';
1034 s [len2++] = 'i';
1035 break;
1036
1037 case '&':
1038 case '|':
1039 case '^':
1040 s [len2++] = '_';
1041 s [len2++] = name [j] == '&' ? 'a' : name [j] == '|' ? 'o' : 'x';
1042
1043 if (name [j + 1] == '=')
1044 {
1045 j++;
1046 s [len2++] = 'e';
1047 }
1048 break;
1049
1050 case '+':
1051 case '-':
1052 case '*':
1053 case '/':
1054 case '(':
1055 case '[':
1056 if (s [len2 - 1] != '_')
1057 s [len2++] = '_';
1058
1059 switch (name [j + 1]) {
1060 case '\0':
1061 j++;
1062 switch (name [j - 1]) {
1063 case '+': s [len2++] = 'p'; break; /* + */
1064 case '-': s [len2++] = 'm'; break; /* - */
1065 case '*': s [len2++] = 't'; break; /* * */
1066 case '/': s [len2++] = 'd'; break; /* / */
1067 }
1068 break;
1069
1070 case '=':
1071 j++;
1072 switch (name [j - 1]) {
1073 case '+': s [len2++] = 'p'; break; /* += */
1074 case '-': s [len2++] = 'm'; break; /* -= */
1075 case '*': s [len2++] = 't'; break; /* *= */
1076 case '/': s [len2++] = 'd'; break; /* /= */
1077 }
1078 s [len2++] = 'a';
1079 break;
1080
1081 case '-': /* -- */
1082 j++;
1083 s [len2++] = 'm';
1084 s [len2++] = 'm';
1085 break;
1086
1087 case '+': /* ++ */
1088 j++;
1089 s [len2++] = 'p';
1090 s [len2++] = 'p';
1091 break;
1092
1093 case ')': /* () */
1094 j++;
1095 s [len2++] = 'o';
1096 s [len2++] = 'p';
1097 break;
1098
1099 case ']': /* [] */
1100 j++;
1101 s [len2++] = 'o';
1102 s [len2++] = 'b';
1103 break;
1104 }
1105
1106 break;
1107
1108 case '<':
1109 case '>':
1110 c = name [j] == '<' ? 'l' : 'g';
1111 s [len2++] = '_';
1112
1113 switch (name [j + 1]) {
1114 case '\0':
1115 s [len2++] = c;
1116 s [len2++] = 't';
1117 break;
1118 case '=':
1119 j++;
1120 s [len2++] = c;
1121 s [len2++] = 'e';
1122 break;
1123 case '>':
1124 j++;
1125 s [len2++] = 's';
1126 s [len2++] = 'r';
1127 break;
1128 case '<':
1129 j++;
1130 s [len2++] = 's';
1131 s [len2++] = 'l';
1132 break;
1133 default:
1134 break;
1135 }
1136 break;
1137
1138 case '_':
1139 if (len2 && s [len2 - 1] == '_')
1140 s [len2++] = 'u';
1141 /* fall through */
1142
1143 default:
1144 s [len2++] = name [j];
1145 }
1146
1147 if (s [len2 - 1] == '_')
1148 s [len2++] = 'u';
1149
1150 s [len2] = '\0';
1151
1152 return s;
1153 }
1154
1155 static bool package_prefix = true;
1156
1157 /* Dump in BUFFER the name of an identifier NODE of type TYPE, following Ada
1158 syntax. LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1159 'with' clause rather than a regular 'with' clause. */
1160
1161 static void
1162 pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
1163 int limited_access)
1164 {
1165 const char *name = IDENTIFIER_POINTER (node);
1166 int space_found = false;
1167 char *s = to_ada_name (name, &space_found);
1168 tree decl;
1169
1170 /* If the entity is a type and comes from another file, generate "package"
1171 prefix. */
1172
1173 decl = get_underlying_decl (type);
1174
1175 if (decl)
1176 {
1177 expanded_location xloc = expand_location (decl_sloc (decl, false));
1178
1179 if (xloc.file && xloc.line)
1180 {
1181 if (xloc.file != source_file_base)
1182 {
1183 switch (TREE_CODE (type))
1184 {
1185 case ENUMERAL_TYPE:
1186 case INTEGER_TYPE:
1187 case REAL_TYPE:
1188 case FIXED_POINT_TYPE:
1189 case BOOLEAN_TYPE:
1190 case REFERENCE_TYPE:
1191 case POINTER_TYPE:
1192 case ARRAY_TYPE:
1193 case RECORD_TYPE:
1194 case UNION_TYPE:
1195 case QUAL_UNION_TYPE:
1196 case TYPE_DECL:
1197 {
1198 char *s1 = get_ada_package (xloc.file);
1199
1200 if (package_prefix)
1201 {
1202 append_withs (s1, limited_access);
1203 pp_string (buffer, s1);
1204 pp_character (buffer, '.');
1205 }
1206 free (s1);
1207 }
1208 break;
1209 default:
1210 break;
1211 }
1212 }
1213 }
1214 }
1215
1216 if (space_found)
1217 if (!strcmp (s, "short_int"))
1218 pp_string (buffer, "short");
1219 else if (!strcmp (s, "short_unsigned_int"))
1220 pp_string (buffer, "unsigned_short");
1221 else if (!strcmp (s, "unsigned_int"))
1222 pp_string (buffer, "unsigned");
1223 else if (!strcmp (s, "long_int"))
1224 pp_string (buffer, "long");
1225 else if (!strcmp (s, "long_unsigned_int"))
1226 pp_string (buffer, "unsigned_long");
1227 else if (!strcmp (s, "long_long_int"))
1228 pp_string (buffer, "Long_Long_Integer");
1229 else if (!strcmp (s, "long_long_unsigned_int"))
1230 {
1231 if (package_prefix)
1232 {
1233 append_withs ("Interfaces.C.Extensions", false);
1234 pp_string (buffer, "Extensions.unsigned_long_long");
1235 }
1236 else
1237 pp_string (buffer, "unsigned_long_long");
1238 }
1239 else
1240 pp_string(buffer, s);
1241 else
1242 if (!strcmp (s, "bool"))
1243 {
1244 if (package_prefix)
1245 {
1246 append_withs ("Interfaces.C.Extensions", false);
1247 pp_string (buffer, "Extensions.bool");
1248 }
1249 else
1250 pp_string (buffer, "bool");
1251 }
1252 else
1253 pp_string(buffer, s);
1254
1255 free (s);
1256 }
1257
1258 /* Dump in BUFFER the assembly name of T. */
1259
1260 static void
1261 pp_asm_name (pretty_printer *buffer, tree t)
1262 {
1263 tree name = DECL_ASSEMBLER_NAME (t);
1264 char *ada_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (name) + 1), *s;
1265 const char *ident = IDENTIFIER_POINTER (name);
1266
1267 for (s = ada_name; *ident; ident++)
1268 {
1269 if (*ident == ' ')
1270 break;
1271 else if (*ident != '*')
1272 *s++ = *ident;
1273 }
1274
1275 *s = '\0';
1276 pp_string (buffer, ada_name);
1277 }
1278
1279 /* Dump in BUFFER the name of a DECL node if set, following Ada syntax.
1280 LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1281 'with' clause rather than a regular 'with' clause. */
1282
1283 static void
1284 dump_ada_decl_name (pretty_printer *buffer, tree decl, int limited_access)
1285 {
1286 if (DECL_NAME (decl))
1287 pp_ada_tree_identifier (buffer, DECL_NAME (decl), decl, limited_access);
1288 else
1289 {
1290 tree type_name = TYPE_NAME (TREE_TYPE (decl));
1291
1292 if (!type_name)
1293 {
1294 pp_string (buffer, "anon");
1295 if (TREE_CODE (decl) == FIELD_DECL)
1296 pp_scalar (buffer, "%d", DECL_UID (decl));
1297 else
1298 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (decl)));
1299 }
1300 else if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1301 pp_ada_tree_identifier (buffer, type_name, decl, limited_access);
1302 }
1303 }
1304
1305 /* Dump in BUFFER a name based on both T1 and T2, followed by S. */
1306
1307 static void
1308 dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2, const char *s)
1309 {
1310 if (DECL_NAME (t1))
1311 pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, false);
1312 else
1313 {
1314 pp_string (buffer, "anon");
1315 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t1)));
1316 }
1317
1318 pp_character (buffer, '_');
1319
1320 if (DECL_NAME (t1))
1321 pp_ada_tree_identifier (buffer, DECL_NAME (t2), t2, false);
1322 else
1323 {
1324 pp_string (buffer, "anon");
1325 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t2)));
1326 }
1327
1328 pp_string (buffer, s);
1329 }
1330
1331 /* Dump in BUFFER pragma Import C/CPP on a given node T. */
1332
1333 static void
1334 dump_ada_import (pretty_printer *buffer, tree t)
1335 {
1336 const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
1337 int is_stdcall = TREE_CODE (t) == FUNCTION_DECL &&
1338 lookup_attribute ("stdcall", TYPE_ATTRIBUTES (TREE_TYPE (t)));
1339
1340 if (is_stdcall)
1341 pp_string (buffer, "pragma Import (Stdcall, ");
1342 else if (name [0] == '_' && name [1] == 'Z')
1343 pp_string (buffer, "pragma Import (CPP, ");
1344 else
1345 pp_string (buffer, "pragma Import (C, ");
1346
1347 dump_ada_decl_name (buffer, t, false);
1348 pp_string (buffer, ", \"");
1349
1350 if (is_stdcall)
1351 pp_string (buffer, IDENTIFIER_POINTER (DECL_NAME (t)));
1352 else
1353 pp_asm_name (buffer, t);
1354
1355 pp_string (buffer, "\");");
1356 }
1357
1358 /* Check whether T and its type have different names, and append "the_"
1359 otherwise in BUFFER. */
1360
1361 static void
1362 check_name (pretty_printer *buffer, tree t)
1363 {
1364 const char *s;
1365 tree tmp = TREE_TYPE (t);
1366
1367 while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp))
1368 tmp = TREE_TYPE (tmp);
1369
1370 if (TREE_CODE (tmp) != FUNCTION_TYPE)
1371 {
1372 if (TREE_CODE (tmp) == IDENTIFIER_NODE)
1373 s = IDENTIFIER_POINTER (tmp);
1374 else if (!TYPE_NAME (tmp))
1375 s = "";
1376 else if (TREE_CODE (TYPE_NAME (tmp)) == IDENTIFIER_NODE)
1377 s = IDENTIFIER_POINTER (TYPE_NAME (tmp));
1378 else
1379 s = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp)));
1380
1381 if (!strcasecmp (IDENTIFIER_POINTER (DECL_NAME (t)), s))
1382 pp_string (buffer, "the_");
1383 }
1384 }
1385
1386 /* Dump in BUFFER a function declaration FUNC with Ada syntax.
1387 IS_METHOD indicates whether FUNC is a C++ method.
1388 IS_CONSTRUCTOR whether FUNC is a C++ constructor.
1389 IS_DESTRUCTOR whether FUNC is a C++ destructor.
1390 SPC is the current indentation level. */
1391
1392 static int
1393 dump_ada_function_declaration (pretty_printer *buffer, tree func,
1394 int is_method, int is_constructor,
1395 int is_destructor, int spc)
1396 {
1397 tree arg;
1398 const tree node = TREE_TYPE (func);
1399 char buf [16];
1400 int num = 0, num_args = 0, have_args = true, have_ellipsis = false;
1401
1402 /* Compute number of arguments. */
1403 arg = TYPE_ARG_TYPES (node);
1404
1405 if (arg)
1406 {
1407 while (TREE_CHAIN (arg) && arg != error_mark_node)
1408 {
1409 num_args++;
1410 arg = TREE_CHAIN (arg);
1411 }
1412
1413 if (TREE_CODE (TREE_VALUE (arg)) != VOID_TYPE)
1414 {
1415 num_args++;
1416 have_ellipsis = true;
1417 }
1418 }
1419
1420 if (is_constructor)
1421 num_args--;
1422
1423 if (is_destructor)
1424 num_args = 1;
1425
1426 if (num_args > 2)
1427 newline_and_indent (buffer, spc + 1);
1428
1429 if (num_args > 0)
1430 {
1431 pp_space (buffer);
1432 pp_character (buffer, '(');
1433 }
1434
1435 if (TREE_CODE (func) == FUNCTION_DECL)
1436 arg = DECL_ARGUMENTS (func);
1437 else
1438 arg = NULL_TREE;
1439
1440 if (arg == NULL_TREE)
1441 {
1442 have_args = false;
1443 arg = TYPE_ARG_TYPES (node);
1444
1445 if (arg && TREE_CODE (TREE_VALUE (arg)) == VOID_TYPE)
1446 arg = NULL_TREE;
1447 }
1448
1449 if (is_constructor)
1450 arg = TREE_CHAIN (arg);
1451
1452 /* Print the argument names (if available) & types. */
1453
1454 for (num = 1; num <= num_args; num++)
1455 {
1456 if (have_args)
1457 {
1458 if (DECL_NAME (arg))
1459 {
1460 check_name (buffer, arg);
1461 pp_ada_tree_identifier (buffer, DECL_NAME (arg), 0, false);
1462 pp_string (buffer, " : ");
1463 }
1464 else
1465 {
1466 sprintf (buf, "arg%d : ", num);
1467 pp_string (buffer, buf);
1468 }
1469
1470 dump_generic_ada_node
1471 (buffer, TREE_TYPE (arg), node, NULL, spc, 0, true);
1472 }
1473 else
1474 {
1475 sprintf (buf, "arg%d : ", num);
1476 pp_string (buffer, buf);
1477 dump_generic_ada_node
1478 (buffer, TREE_VALUE (arg), node, NULL, spc, 0, true);
1479 }
1480
1481 if (TREE_TYPE (arg) && TREE_TYPE (TREE_TYPE (arg))
1482 && is_tagged_type (TREE_TYPE (TREE_TYPE (arg))))
1483 {
1484 if (!is_method
1485 || (num != 1 || (!DECL_VINDEX (func) && !is_constructor)))
1486 pp_string (buffer, "'Class");
1487 }
1488
1489 arg = TREE_CHAIN (arg);
1490
1491 if (num < num_args)
1492 {
1493 pp_character (buffer, ';');
1494
1495 if (num_args > 2)
1496 newline_and_indent (buffer, spc + INDENT_INCR);
1497 else
1498 pp_space (buffer);
1499 }
1500 }
1501
1502 if (have_ellipsis)
1503 {
1504 pp_string (buffer, " -- , ...");
1505 newline_and_indent (buffer, spc + INDENT_INCR);
1506 }
1507
1508 if (num_args > 0)
1509 pp_character (buffer, ')');
1510 return num_args;
1511 }
1512
1513 /* Dump in BUFFER all the domains associated with an array NODE,
1514 using Ada syntax. SPC is the current indentation level. */
1515
1516 static void
1517 dump_ada_array_domains (pretty_printer *buffer, tree node, int spc)
1518 {
1519 int first = 1;
1520 pp_character (buffer, '(');
1521
1522 for (; TREE_CODE (node) == ARRAY_TYPE; node = TREE_TYPE (node))
1523 {
1524 tree domain = TYPE_DOMAIN (node);
1525
1526 if (domain)
1527 {
1528 tree min = TYPE_MIN_VALUE (domain);
1529 tree max = TYPE_MAX_VALUE (domain);
1530
1531 if (!first)
1532 pp_string (buffer, ", ");
1533 first = 0;
1534
1535 if (min)
1536 dump_generic_ada_node (buffer, min, NULL_TREE, NULL, spc, 0, true);
1537 pp_string (buffer, " .. ");
1538
1539 /* If the upper bound is zero, gcc may generate a NULL_TREE
1540 for TYPE_MAX_VALUE rather than an integer_cst. */
1541 if (max)
1542 dump_generic_ada_node (buffer, max, NULL_TREE, NULL, spc, 0, true);
1543 else
1544 pp_string (buffer, "0");
1545 }
1546 else
1547 pp_string (buffer, "size_t");
1548 }
1549 pp_character (buffer, ')');
1550 }
1551
1552 /* Dump in BUFFER file:line information related to NODE. */
1553
1554 static void
1555 dump_sloc (pretty_printer *buffer, tree node)
1556 {
1557 expanded_location xloc;
1558
1559 xloc.file = NULL;
1560
1561 if (TREE_CODE_CLASS (TREE_CODE (node)) == tcc_declaration)
1562 xloc = expand_location (DECL_SOURCE_LOCATION (node));
1563 else if (EXPR_HAS_LOCATION (node))
1564 xloc = expand_location (EXPR_LOCATION (node));
1565
1566 if (xloc.file)
1567 {
1568 pp_string (buffer, xloc.file);
1569 pp_string (buffer, ":");
1570 pp_decimal_int (buffer, xloc.line);
1571 }
1572 }
1573
1574 /* Return true if T designates a one dimension array of "char". */
1575
1576 static bool
1577 is_char_array (tree t)
1578 {
1579 tree tmp;
1580 int num_dim = 0;
1581
1582 /* Retrieve array's type. */
1583 tmp = t;
1584 while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1585 {
1586 num_dim++;
1587 tmp = TREE_TYPE (tmp);
1588 }
1589
1590 tmp = TREE_TYPE (tmp);
1591 return num_dim == 1 && TREE_CODE (tmp) == INTEGER_TYPE
1592 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp))), "char");
1593 }
1594
1595 /* Dump in BUFFER an array type T in Ada syntax. Assume that the "type"
1596 keyword and name have already been printed. SPC is the indentation
1597 level. */
1598
1599 static void
1600 dump_ada_array_type (pretty_printer *buffer, tree t, int spc)
1601 {
1602 tree tmp;
1603 bool char_array = is_char_array (t);
1604
1605 /* Special case char arrays. */
1606 if (char_array)
1607 {
1608 pp_string (buffer, "Interfaces.C.char_array ");
1609 }
1610 else
1611 pp_string (buffer, "array ");
1612
1613 /* Print the dimensions. */
1614 dump_ada_array_domains (buffer, TREE_TYPE (t), spc);
1615
1616 /* Retrieve array's type. */
1617 tmp = TREE_TYPE (t);
1618 while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1619 tmp = TREE_TYPE (tmp);
1620
1621 /* Print array's type. */
1622 if (!char_array)
1623 {
1624 pp_string (buffer, " of ");
1625
1626 if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE)
1627 pp_string (buffer, "aliased ");
1628
1629 dump_generic_ada_node
1630 (buffer, TREE_TYPE (tmp), TREE_TYPE (t), NULL, spc, false, true);
1631 }
1632 }
1633
1634 /* Dump in BUFFER type names associated with a template, each prepended with
1635 '_'. TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.
1636 CPP_CHECK is used to perform C++ queries on nodes.
1637 SPC is the indentation level. */
1638
1639 static void
1640 dump_template_types (pretty_printer *buffer, tree types,
1641 int (*cpp_check)(tree, cpp_operation), int spc)
1642 {
1643 size_t i;
1644 size_t len = TREE_VEC_LENGTH (types);
1645
1646 for (i = 0; i < len; i++)
1647 {
1648 tree elem = TREE_VEC_ELT (types, i);
1649 pp_character (buffer, '_');
1650 if (!dump_generic_ada_node (buffer, elem, 0, cpp_check, spc, false, true))
1651 {
1652 pp_string (buffer, "unknown");
1653 pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
1654 }
1655 }
1656 }
1657
1658 /* Dump in BUFFER the contents of all instantiations associated with a given
1659 template T. CPP_CHECK is used to perform C++ queries on nodes.
1660 SPC is the indentation level. */
1661
1662 static int
1663 dump_ada_template (pretty_printer *buffer, tree t,
1664 int (*cpp_check)(tree, cpp_operation), int spc)
1665 {
1666 tree inst = DECL_VINDEX (t);
1667 /* DECL_VINDEX is DECL_TEMPLATE_INSTANTIATIONS in this context. */
1668 int num_inst = 0;
1669
1670 while (inst && inst != error_mark_node)
1671 {
1672 tree types = TREE_PURPOSE (inst);
1673 tree instance = TREE_VALUE (inst);
1674
1675 if (TREE_VEC_LENGTH (types) == 0)
1676 break;
1677
1678 if (!TYPE_METHODS (instance))
1679 break;
1680
1681 num_inst++;
1682 INDENT (spc);
1683 pp_string (buffer, "package ");
1684 package_prefix = false;
1685 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1686 dump_template_types (buffer, types, cpp_check, spc);
1687 pp_string (buffer, " is");
1688 spc += INDENT_INCR;
1689 newline_and_indent (buffer, spc);
1690
1691 pp_string (buffer, "type ");
1692 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1693 package_prefix = true;
1694
1695 if (is_tagged_type (instance))
1696 pp_string (buffer, " is tagged limited ");
1697 else
1698 pp_string (buffer, " is limited ");
1699
1700 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, false);
1701 pp_newline (buffer);
1702 spc -= INDENT_INCR;
1703 newline_and_indent (buffer, spc);
1704
1705 pp_string (buffer, "end;");
1706 newline_and_indent (buffer, spc);
1707 pp_string (buffer, "use ");
1708 package_prefix = false;
1709 dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
1710 dump_template_types (buffer, types, cpp_check, spc);
1711 package_prefix = true;
1712 pp_semicolon (buffer);
1713 pp_newline (buffer);
1714 pp_newline (buffer);
1715
1716 inst = TREE_CHAIN (inst);
1717 }
1718
1719 return num_inst > 0;
1720 }
1721
1722 /* Return true if NODE is a simple enum types, that can be mapped to an
1723 Ada enum type directly. */
1724
1725 static bool
1726 is_simple_enum (tree node)
1727 {
1728 unsigned HOST_WIDE_INT count = 0;
1729 tree value;
1730
1731 for (value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
1732 {
1733 tree int_val = TREE_VALUE (value);
1734
1735 if (TREE_CODE (int_val) != INTEGER_CST)
1736 int_val = DECL_INITIAL (int_val);
1737
1738 if (!host_integerp (int_val, 0))
1739 return false;
1740 else if (TREE_INT_CST_LOW (int_val) != count)
1741 return false;
1742
1743 count++;
1744 }
1745
1746 return true;
1747 }
1748
1749 static bool in_function = true;
1750 static bool bitfield_used = false;
1751
1752 /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
1753 TYPE. CPP_CHECK is used to perform C++ queries on nodes. SPC is the
1754 indentation level. LIMITED_ACCESS indicates whether NODE can be referenced
1755 via a "limited with" clause. NAME_ONLY indicates whether we should only
1756 dump the name of NODE, instead of its full declaration. */
1757
1758 static int
1759 dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
1760 int (*cpp_check)(tree, cpp_operation), int spc,
1761 int limited_access, bool name_only)
1762 {
1763 if (node == NULL_TREE)
1764 return 0;
1765
1766 switch (TREE_CODE (node))
1767 {
1768 case ERROR_MARK:
1769 pp_string (buffer, "<<< error >>>");
1770 return 0;
1771
1772 case IDENTIFIER_NODE:
1773 pp_ada_tree_identifier (buffer, node, type, limited_access);
1774 break;
1775
1776 case TREE_LIST:
1777 pp_string (buffer, "--- unexpected node: TREE_LIST");
1778 return 0;
1779
1780 case TREE_BINFO:
1781 dump_generic_ada_node
1782 (buffer, BINFO_TYPE (node), type, cpp_check,
1783 spc, limited_access, name_only);
1784
1785 case TREE_VEC:
1786 pp_string (buffer, "--- unexpected node: TREE_VEC");
1787 return 0;
1788
1789 case VOID_TYPE:
1790 if (package_prefix)
1791 {
1792 append_withs ("System", false);
1793 pp_string (buffer, "System.Address");
1794 }
1795 else
1796 pp_string (buffer, "address");
1797 break;
1798
1799 case VECTOR_TYPE:
1800 pp_string (buffer, "<vector>");
1801 break;
1802
1803 case COMPLEX_TYPE:
1804 pp_string (buffer, "<complex>");
1805 break;
1806
1807 case ENUMERAL_TYPE:
1808 if (name_only)
1809 dump_generic_ada_node
1810 (buffer, TYPE_NAME (node), node, cpp_check, spc, 0, true);
1811 else
1812 {
1813 tree value = TYPE_VALUES (node);
1814
1815 if (is_simple_enum (node))
1816 {
1817 bool first = true;
1818 spc += INDENT_INCR;
1819 newline_and_indent (buffer, spc - 1);
1820 pp_string (buffer, "(");
1821 for (; value; value = TREE_CHAIN (value))
1822 {
1823 if (first)
1824 first = false;
1825 else
1826 {
1827 pp_string (buffer, ",");
1828 newline_and_indent (buffer, spc);
1829 }
1830
1831 pp_ada_tree_identifier
1832 (buffer, TREE_PURPOSE (value), node, false);
1833 }
1834 pp_string (buffer, ");");
1835 spc -= INDENT_INCR;
1836 newline_and_indent (buffer, spc);
1837 pp_string (buffer, "pragma Convention (C, ");
1838 dump_generic_ada_node
1839 (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
1840 cpp_check, spc, 0, true);
1841 pp_string (buffer, ")");
1842 }
1843 else
1844 {
1845 pp_string (buffer, "unsigned");
1846 for (; value; value = TREE_CHAIN (value))
1847 {
1848 pp_semicolon (buffer);
1849 newline_and_indent (buffer, spc);
1850
1851 pp_ada_tree_identifier
1852 (buffer, TREE_PURPOSE (value), node, false);
1853 pp_string (buffer, " : constant ");
1854
1855 dump_generic_ada_node
1856 (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
1857 cpp_check, spc, 0, true);
1858
1859 pp_string (buffer, " := ");
1860 dump_generic_ada_node
1861 (buffer,
1862 TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ?
1863 TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)),
1864 node, cpp_check, spc, false, true);
1865 }
1866 }
1867 }
1868 break;
1869
1870 case INTEGER_TYPE:
1871 case REAL_TYPE:
1872 case FIXED_POINT_TYPE:
1873 case BOOLEAN_TYPE:
1874 {
1875 enum tree_code_class tclass;
1876
1877 tclass = TREE_CODE_CLASS (TREE_CODE (node));
1878
1879 if (tclass == tcc_declaration)
1880 {
1881 if (DECL_NAME (node))
1882 pp_ada_tree_identifier
1883 (buffer, DECL_NAME (node), 0, limited_access);
1884 else
1885 pp_string (buffer, "<unnamed type decl>");
1886 }
1887 else if (tclass == tcc_type)
1888 {
1889 if (TYPE_NAME (node))
1890 {
1891 if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
1892 pp_ada_tree_identifier (buffer, TYPE_NAME (node),
1893 node, limited_access);
1894 else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
1895 && DECL_NAME (TYPE_NAME (node)))
1896 dump_ada_decl_name (buffer, TYPE_NAME (node), limited_access);
1897 else
1898 pp_string (buffer, "<unnamed type>");
1899 }
1900 else if (TREE_CODE (node) == INTEGER_TYPE)
1901 {
1902 append_withs ("Interfaces.C.Extensions", false);
1903 bitfield_used = true;
1904
1905 if (TYPE_PRECISION (node) == 1)
1906 pp_string (buffer, "Extensions.Unsigned_1");
1907 else
1908 {
1909 pp_string (buffer, (TYPE_UNSIGNED (node)
1910 ? "Extensions.Unsigned_"
1911 : "Extensions.Signed_"));
1912 pp_decimal_int (buffer, TYPE_PRECISION (node));
1913 }
1914 }
1915 else
1916 pp_string (buffer, "<unnamed type>");
1917 }
1918 break;
1919 }
1920
1921 case POINTER_TYPE:
1922 case REFERENCE_TYPE:
1923 if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
1924 {
1925 tree fnode = TREE_TYPE (node);
1926 bool is_function;
1927 bool prev_in_function = in_function;
1928
1929 if (VOID_TYPE_P (TREE_TYPE (fnode)))
1930 {
1931 is_function = false;
1932 pp_string (buffer, "access procedure");
1933 }
1934 else
1935 {
1936 is_function = true;
1937 pp_string (buffer, "access function");
1938 }
1939
1940 in_function = is_function;
1941 dump_ada_function_declaration
1942 (buffer, node, false, false, false, spc + INDENT_INCR);
1943 in_function = prev_in_function;
1944
1945 if (is_function)
1946 {
1947 pp_string (buffer, " return ");
1948 dump_generic_ada_node
1949 (buffer, TREE_TYPE (fnode), type, cpp_check, spc, 0, true);
1950 }
1951 }
1952 else
1953 {
1954 int is_access = false;
1955 unsigned int quals = TYPE_QUALS (TREE_TYPE (node));
1956
1957 if (name_only && TYPE_NAME (node))
1958 dump_generic_ada_node
1959 (buffer, TYPE_NAME (node), node, cpp_check,
1960 spc, limited_access, true);
1961 else if (VOID_TYPE_P (TREE_TYPE (node)))
1962 {
1963 if (!name_only)
1964 pp_string (buffer, "new ");
1965 if (package_prefix)
1966 {
1967 append_withs ("System", false);
1968 pp_string (buffer, "System.Address");
1969 }
1970 else
1971 pp_string (buffer, "address");
1972 }
1973 else
1974 {
1975 if (TREE_CODE (node) == POINTER_TYPE
1976 && TREE_CODE (TREE_TYPE (node)) == INTEGER_TYPE
1977 && !strcmp
1978 (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME
1979 (TREE_TYPE (node)))), "char"))
1980 {
1981 if (!name_only)
1982 pp_string (buffer, "new ");
1983
1984 if (package_prefix)
1985 {
1986 pp_string (buffer, "Interfaces.C.Strings.chars_ptr");
1987 append_withs ("Interfaces.C.Strings", false);
1988 }
1989 else
1990 pp_string (buffer, "chars_ptr");
1991 }
1992 else
1993 {
1994 /* For now, handle all access-to-access or
1995 access-to-unknown-structs as opaque system.address. */
1996
1997 tree typ = TYPE_NAME (TREE_TYPE (node));
1998 const_tree typ2 = !type ||
1999 DECL_P (type) ? type : TYPE_NAME (type);
2000 const_tree underlying_type =
2001 get_underlying_decl (TREE_TYPE (node));
2002
2003 if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE
2004 /* Pointer to pointer. */
2005
2006 || (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2007 && (!underlying_type
2008 || !TYPE_FIELDS (TREE_TYPE (underlying_type))))
2009 /* Pointer to opaque structure. */
2010
2011 || (typ && typ2
2012 && DECL_P (underlying_type)
2013 && DECL_P (typ2)
2014 && decl_sloc (underlying_type, true)
2015 > decl_sloc (typ2, true)
2016 && DECL_SOURCE_FILE (underlying_type)
2017 == DECL_SOURCE_FILE (typ2)))
2018 {
2019 if (package_prefix)
2020 {
2021 append_withs ("System", false);
2022 if (!name_only)
2023 pp_string (buffer, "new ");
2024 pp_string (buffer, "System.Address");
2025 }
2026 else
2027 pp_string (buffer, "address");
2028 return spc;
2029 }
2030
2031 if (!package_prefix)
2032 pp_string (buffer, "access");
2033 else if (AGGREGATE_TYPE_P (TREE_TYPE (node)))
2034 {
2035 if (!type || TREE_CODE (type) != FUNCTION_DECL)
2036 {
2037 pp_string (buffer, "access ");
2038 is_access = true;
2039
2040 if (quals & TYPE_QUAL_CONST)
2041 pp_string (buffer, "constant ");
2042 else if (!name_only)
2043 pp_string (buffer, "all ");
2044 }
2045 else if (quals & TYPE_QUAL_CONST)
2046 pp_string (buffer, "in ");
2047 else if (in_function)
2048 {
2049 is_access = true;
2050 pp_string (buffer, "access ");
2051 }
2052 else
2053 {
2054 is_access = true;
2055 pp_string (buffer, "access ");
2056 /* ??? should be configurable: access or in out. */
2057 }
2058 }
2059 else
2060 {
2061 is_access = true;
2062 pp_string (buffer, "access ");
2063
2064 if (!name_only)
2065 pp_string (buffer, "all ");
2066 }
2067
2068 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2069 && TYPE_NAME (TREE_TYPE (node)))
2070 {
2071 tree name = TYPE_NAME (TREE_TYPE (node));
2072 tree tmp;
2073
2074 if (TREE_CODE (name) == TYPE_DECL
2075 && DECL_ORIGINAL_TYPE (name)
2076 && TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (name)))
2077 {
2078 tmp = TYPE_NAME (TREE_TYPE (TYPE_STUB_DECL
2079 (DECL_ORIGINAL_TYPE (name))));
2080
2081 if (tmp == NULL_TREE)
2082 tmp = TYPE_NAME (TREE_TYPE (node));
2083 }
2084 else
2085 tmp = TYPE_NAME (TREE_TYPE (node));
2086
2087 dump_generic_ada_node
2088 (buffer, tmp,
2089 TREE_TYPE (node), cpp_check, spc, is_access, true);
2090 }
2091 else
2092 dump_generic_ada_node
2093 (buffer, TREE_TYPE (node), TREE_TYPE (node),
2094 cpp_check, spc, 0, true);
2095 }
2096 }
2097 }
2098 break;
2099
2100 case ARRAY_TYPE:
2101 if (name_only)
2102 dump_generic_ada_node
2103 (buffer, TYPE_NAME (node), node, cpp_check,
2104 spc, limited_access, true);
2105 else
2106 dump_ada_array_type (buffer, node, spc);
2107 break;
2108
2109 case RECORD_TYPE:
2110 case UNION_TYPE:
2111 case QUAL_UNION_TYPE:
2112 if (name_only)
2113 {
2114 if (TYPE_NAME (node))
2115 dump_generic_ada_node
2116 (buffer, TYPE_NAME (node), node, cpp_check,
2117 spc, limited_access, true);
2118 else
2119 {
2120 pp_string (buffer, "anon_");
2121 pp_scalar (buffer, "%d", TYPE_UID (node));
2122 }
2123 }
2124 else
2125 print_ada_struct_decl
2126 (buffer, node, type, cpp_check, spc, true);
2127 break;
2128
2129 case INTEGER_CST:
2130 if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE)
2131 {
2132 pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
2133 pp_string (buffer, "B"); /* pseudo-unit */
2134 }
2135 else if (!host_integerp (node, 0))
2136 {
2137 tree val = node;
2138 unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (val);
2139 HOST_WIDE_INT high = TREE_INT_CST_HIGH (val);
2140
2141 if (tree_int_cst_sgn (val) < 0)
2142 {
2143 pp_character (buffer, '-');
2144 high = ~high + !low;
2145 low = -low;
2146 }
2147 sprintf (pp_buffer (buffer)->digit_buffer,
2148 HOST_WIDE_INT_PRINT_DOUBLE_HEX,
2149 (unsigned HOST_WIDE_INT) high, low);
2150 pp_string (buffer, pp_buffer (buffer)->digit_buffer);
2151 }
2152 else
2153 pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
2154 break;
2155
2156 case REAL_CST:
2157 case FIXED_CST:
2158 case COMPLEX_CST:
2159 case STRING_CST:
2160 case VECTOR_CST:
2161 return 0;
2162
2163 case FUNCTION_DECL:
2164 case CONST_DECL:
2165 dump_ada_decl_name (buffer, node, limited_access);
2166 break;
2167
2168 case TYPE_DECL:
2169 if (DECL_IS_BUILTIN (node))
2170 {
2171 /* Don't print the declaration of built-in types. */
2172
2173 if (name_only)
2174 {
2175 /* If we're in the middle of a declaration, defaults to
2176 System.Address. */
2177 if (package_prefix)
2178 {
2179 append_withs ("System", false);
2180 pp_string (buffer, "System.Address");
2181 }
2182 else
2183 pp_string (buffer, "address");
2184 }
2185 break;
2186 }
2187
2188 if (name_only)
2189 dump_ada_decl_name (buffer, node, limited_access);
2190 else
2191 {
2192 if (is_tagged_type (TREE_TYPE (node)))
2193 {
2194 tree tmp = TYPE_FIELDS (TREE_TYPE (node));
2195 int first = 1;
2196
2197 /* Look for ancestors. */
2198 for (; tmp; tmp = TREE_CHAIN (tmp))
2199 {
2200 if (!DECL_NAME (tmp) && is_tagged_type (TREE_TYPE (tmp)))
2201 {
2202 if (first)
2203 {
2204 pp_string (buffer, "limited new ");
2205 first = 0;
2206 }
2207 else
2208 pp_string (buffer, " and ");
2209
2210 dump_ada_decl_name
2211 (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
2212 }
2213 }
2214
2215 pp_string (buffer, first ? "tagged limited " : " with ");
2216 }
2217 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
2218 && TYPE_METHODS (TREE_TYPE (node)))
2219 pp_string (buffer, "limited ");
2220
2221 dump_generic_ada_node
2222 (buffer, TREE_TYPE (node), type, cpp_check, spc, false, false);
2223 }
2224 break;
2225
2226 case VAR_DECL:
2227 case PARM_DECL:
2228 case FIELD_DECL:
2229 case NAMESPACE_DECL:
2230 dump_ada_decl_name (buffer, node, false);
2231 break;
2232
2233 default:
2234 /* Ignore other nodes (e.g. expressions). */
2235 return 0;
2236 }
2237
2238 return 1;
2239 }
2240
2241 /* Dump in BUFFER NODE's methods. CPP_CHECK is used to perform C++ queries on
2242 nodes. SPC is the indentation level. */
2243
2244 static void
2245 print_ada_methods (pretty_printer *buffer, tree node,
2246 int (*cpp_check)(tree, cpp_operation), int spc)
2247 {
2248 tree tmp = TYPE_METHODS (node);
2249 int res = 1;
2250
2251 if (tmp)
2252 {
2253 pp_semicolon (buffer);
2254
2255 for (; tmp; tmp = TREE_CHAIN (tmp))
2256 {
2257 if (res)
2258 {
2259 pp_newline (buffer);
2260 pp_newline (buffer);
2261 }
2262 res = print_ada_declaration (buffer, tmp, node, cpp_check, spc);
2263 }
2264 }
2265 }
2266
2267 /* Dump in BUFFER anonymous types nested inside T's definition.
2268 PARENT is the parent node of T. CPP_CHECK is used to perform C++ queries on
2269 nodes. SPC is the indentation level. */
2270
2271 static void
2272 dump_nested_types (pretty_printer *buffer, tree t, tree parent,
2273 int (*cpp_check)(tree, cpp_operation), int spc)
2274 {
2275 tree field, outer, decl;
2276
2277 /* Avoid recursing over the same tree. */
2278 if (TREE_VISITED (t))
2279 return;
2280
2281 /* Find possible anonymous arrays/unions/structs recursively. */
2282
2283 outer = TREE_TYPE (t);
2284
2285 if (outer == NULL_TREE)
2286 return;
2287
2288 field = TYPE_FIELDS (outer);
2289 while (field)
2290 {
2291 if ((TREE_TYPE (field) != outer
2292 || (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2293 && TREE_TYPE (TREE_TYPE (field)) != outer))
2294 && (!TYPE_NAME (TREE_TYPE (field))
2295 || (TREE_CODE (field) == TYPE_DECL
2296 && DECL_NAME (field) != DECL_NAME (t)
2297 && TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (outer))))
2298 {
2299 switch (TREE_CODE (TREE_TYPE (field)))
2300 {
2301 case POINTER_TYPE:
2302 decl = TREE_TYPE (TREE_TYPE (field));
2303
2304 if (TREE_CODE (decl) == FUNCTION_TYPE)
2305 for (decl = TREE_TYPE (decl);
2306 decl && TREE_CODE (decl) == POINTER_TYPE;
2307 decl = TREE_TYPE (decl));
2308
2309 decl = get_underlying_decl (decl);
2310
2311 if (decl
2312 && DECL_P (decl)
2313 && decl_sloc (decl, true) > decl_sloc (t, true)
2314 && DECL_SOURCE_FILE (decl) == DECL_SOURCE_FILE (t)
2315 && !TREE_VISITED (decl)
2316 && !DECL_IS_BUILTIN (decl)
2317 && (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
2318 || TYPE_FIELDS (TREE_TYPE (decl))))
2319 {
2320 /* Generate forward declaration. */
2321
2322 pp_string (buffer, "type ");
2323 dump_generic_ada_node
2324 (buffer, decl, 0, cpp_check, spc, false, true);
2325 pp_semicolon (buffer);
2326 newline_and_indent (buffer, spc);
2327
2328 /* Ensure we do not generate duplicate forward
2329 declarations for this type. */
2330 TREE_VISITED (decl) = 1;
2331 }
2332 break;
2333
2334 case ARRAY_TYPE:
2335 /* Special case char arrays. */
2336 if (is_char_array (field))
2337 pp_string (buffer, "sub");
2338
2339 pp_string (buffer, "type ");
2340 dump_ada_double_name (buffer, parent, field, "_array is ");
2341 dump_ada_array_type (buffer, field, spc);
2342 pp_semicolon (buffer);
2343 newline_and_indent (buffer, spc);
2344 break;
2345
2346 case UNION_TYPE:
2347 TREE_VISITED (t) = 1;
2348 dump_nested_types (buffer, field, t, cpp_check, spc);
2349
2350 pp_string (buffer, "type ");
2351
2352 if (TYPE_NAME (TREE_TYPE (field)))
2353 {
2354 dump_generic_ada_node
2355 (buffer, TYPE_NAME (TREE_TYPE (field)), 0, cpp_check,
2356 spc, false, true);
2357 pp_string (buffer, " (discr : unsigned := 0) is ");
2358 print_ada_struct_decl
2359 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2360
2361 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2362 dump_generic_ada_node
2363 (buffer, TREE_TYPE (field), 0, cpp_check,
2364 spc, false, true);
2365 pp_string (buffer, ");");
2366 newline_and_indent (buffer, spc);
2367
2368 pp_string (buffer, "pragma Unchecked_Union (");
2369 dump_generic_ada_node
2370 (buffer, TREE_TYPE (field), 0, cpp_check,
2371 spc, false, true);
2372 pp_string (buffer, ");");
2373 }
2374 else
2375 {
2376 dump_ada_double_name
2377 (buffer, parent, field,
2378 "_union (discr : unsigned := 0) is ");
2379 print_ada_struct_decl
2380 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2381 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2382 dump_ada_double_name (buffer, parent, field, "_union);");
2383 newline_and_indent (buffer, spc);
2384
2385 pp_string (buffer, "pragma Unchecked_Union (");
2386 dump_ada_double_name (buffer, parent, field, "_union);");
2387 }
2388
2389 newline_and_indent (buffer, spc);
2390 break;
2391
2392 case RECORD_TYPE:
2393 if (TYPE_NAME (TREE_TYPE (t)) && !TREE_VISITED (t))
2394 {
2395 pp_string (buffer, "type ");
2396 dump_generic_ada_node
2397 (buffer, t, parent, 0, spc, false, true);
2398 pp_semicolon (buffer);
2399 newline_and_indent (buffer, spc);
2400 }
2401
2402 TREE_VISITED (t) = 1;
2403 dump_nested_types (buffer, field, t, cpp_check, spc);
2404 pp_string (buffer, "type ");
2405
2406 if (TYPE_NAME (TREE_TYPE (field)))
2407 {
2408 dump_generic_ada_node
2409 (buffer, TREE_TYPE (field), 0, cpp_check,
2410 spc, false, true);
2411 pp_string (buffer, " is ");
2412 print_ada_struct_decl
2413 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2414 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2415 dump_generic_ada_node
2416 (buffer, TREE_TYPE (field), 0, cpp_check,
2417 spc, false, true);
2418 pp_string (buffer, ");");
2419 }
2420 else
2421 {
2422 dump_ada_double_name
2423 (buffer, parent, field, "_struct is ");
2424 print_ada_struct_decl
2425 (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
2426 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2427 dump_ada_double_name (buffer, parent, field, "_struct);");
2428 }
2429
2430 newline_and_indent (buffer, spc);
2431 break;
2432
2433 default:
2434 break;
2435 }
2436 }
2437 field = TREE_CHAIN (field);
2438 }
2439 }
2440
2441 /* Dump in BUFFER destructor spec corresponding to T. */
2442
2443 static void
2444 print_destructor (pretty_printer *buffer, tree t)
2445 {
2446 const char *s = IDENTIFIER_POINTER (DECL_NAME (t));
2447
2448 if (*s == '_')
2449 for (s += 2; *s != ' '; s++)
2450 pp_character (buffer, *s);
2451 else
2452 {
2453 pp_string (buffer, "Delete_");
2454 pp_ada_tree_identifier (buffer, DECL_NAME (t), t, false);
2455 }
2456 }
2457
2458 /* Return the name of type T. */
2459
2460 static const char *
2461 type_name (tree t)
2462 {
2463 tree n = TYPE_NAME (t);
2464
2465 if (TREE_CODE (n) == IDENTIFIER_NODE)
2466 return IDENTIFIER_POINTER (n);
2467 else
2468 return IDENTIFIER_POINTER (DECL_NAME (n));
2469 }
2470
2471 /* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
2472 CPP_CHECK is used to perform C++ queries on nodes. SPC is the indentation
2473 level. Return 1 if a declaration was printed, 0 otherwise. */
2474
2475 static int
2476 print_ada_declaration (pretty_printer *buffer, tree t, tree type,
2477 int (*cpp_check)(tree, cpp_operation), int spc)
2478 {
2479 int is_var = 0, need_indent = 0;
2480 int is_class = false;
2481 tree name = TYPE_NAME (TREE_TYPE (t));
2482 tree decl_name = DECL_NAME (t);
2483 bool dump_internal = get_dump_file_info (TDI_ada)->flags & TDF_RAW;
2484 tree orig = NULL_TREE;
2485
2486 if (cpp_check && cpp_check (t, IS_TEMPLATE))
2487 return dump_ada_template (buffer, t, cpp_check, spc);
2488
2489 if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
2490 /* Skip enumeral values: will be handled as part of the type itself. */
2491 return 0;
2492
2493 if (TREE_CODE (t) == TYPE_DECL)
2494 {
2495 orig = DECL_ORIGINAL_TYPE (t);
2496
2497 if (orig && TYPE_STUB_DECL (orig))
2498 {
2499 tree typ = TREE_TYPE (TYPE_STUB_DECL (orig));
2500
2501 if (TYPE_NAME (typ))
2502 {
2503 /* If types have same representation, and same name (ignoring
2504 casing), then ignore the second type. */
2505 if (type_name (typ) == type_name (TREE_TYPE (t))
2506 || !strcasecmp (type_name (typ), type_name (TREE_TYPE (t))))
2507 return 0;
2508
2509 INDENT (spc);
2510
2511 if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ))
2512 {
2513 pp_string (buffer, "-- skipped empty struct ");
2514 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2515 }
2516 else
2517 {
2518 pp_string (buffer, "subtype ");
2519 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2520 pp_string (buffer, " is ");
2521 dump_generic_ada_node
2522 (buffer, typ, type, 0, spc, false, true);
2523 pp_semicolon (buffer);
2524 }
2525 return 1;
2526 }
2527 }
2528
2529 /* Skip unnamed or anonymous structs/unions/enum types. */
2530 if (!orig && !decl_name && !name)
2531 {
2532 tree tmp;
2533 location_t sloc;
2534
2535 if (cpp_check || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
2536 return 0;
2537
2538 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
2539 {
2540 /* Search next items until finding a named type decl. */
2541 sloc = decl_sloc_common (t, true, true);
2542
2543 for (tmp = TREE_CHAIN (t); tmp; tmp = TREE_CHAIN (tmp))
2544 {
2545 if (TREE_CODE (tmp) == TYPE_DECL
2546 && (DECL_NAME (tmp) || TYPE_NAME (TREE_TYPE (tmp))))
2547 {
2548 /* If same sloc, it means we can ignore the anonymous
2549 struct. */
2550 if (decl_sloc_common (tmp, true, true) == sloc)
2551 return 0;
2552 else
2553 break;
2554 }
2555 }
2556 if (tmp == NULL)
2557 return 0;
2558 }
2559 }
2560
2561 if (!orig
2562 && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE
2563 && decl_name
2564 && (*IDENTIFIER_POINTER (decl_name) == '.'
2565 || *IDENTIFIER_POINTER (decl_name) == '$'))
2566 /* Skip anonymous enum types (duplicates of real types). */
2567 return 0;
2568
2569 INDENT (spc);
2570
2571 switch (TREE_CODE (TREE_TYPE (t)))
2572 {
2573 case RECORD_TYPE:
2574 case UNION_TYPE:
2575 case QUAL_UNION_TYPE:
2576 /* Skip empty structs (typically forward references to real
2577 structs). */
2578 if (!TYPE_FIELDS (TREE_TYPE (t)))
2579 {
2580 pp_string (buffer, "-- skipped empty struct ");
2581 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2582 return 1;
2583 }
2584
2585 if (decl_name
2586 && (*IDENTIFIER_POINTER (decl_name) == '.'
2587 || *IDENTIFIER_POINTER (decl_name) == '$'))
2588 {
2589 pp_string (buffer, "-- skipped anonymous struct ");
2590 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2591 return 1;
2592 }
2593
2594 if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2595 pp_string (buffer, "subtype ");
2596 else
2597 {
2598 dump_nested_types (buffer, t, t, cpp_check, spc);
2599
2600 if (TYPE_METHODS (TREE_TYPE (t))
2601 || has_static_fields (TREE_TYPE (t)))
2602 {
2603 is_class = true;
2604 pp_string (buffer, "package Class_");
2605 dump_generic_ada_node
2606 (buffer, t, type, 0, spc, false, true);
2607 pp_string (buffer, " is");
2608 spc += INDENT_INCR;
2609 newline_and_indent (buffer, spc);
2610 }
2611
2612 pp_string (buffer, "type ");
2613 }
2614 break;
2615
2616 case ARRAY_TYPE:
2617 case POINTER_TYPE:
2618 case REFERENCE_TYPE:
2619 if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2620 || is_char_array (t))
2621 pp_string (buffer, "subtype ");
2622 else
2623 pp_string (buffer, "type ");
2624 break;
2625
2626 case FUNCTION_TYPE:
2627 pp_string (buffer, "-- skipped function type ");
2628 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2629 return 1;
2630 break;
2631
2632 case ENUMERAL_TYPE:
2633 if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2634 || !is_simple_enum (TREE_TYPE (t)))
2635 pp_string (buffer, "subtype ");
2636 else
2637 pp_string (buffer, "type ");
2638 break;
2639
2640 default:
2641 pp_string (buffer, "subtype ");
2642 }
2643 }
2644 else
2645 {
2646 if (!dump_internal
2647 && TREE_CODE (t) == VAR_DECL
2648 && decl_name
2649 && *IDENTIFIER_POINTER (decl_name) == '_')
2650 return 0;
2651
2652 need_indent = 1;
2653 }
2654
2655 /* Print the type and name. */
2656 if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
2657 {
2658 if (need_indent)
2659 INDENT (spc);
2660
2661 /* Print variable's name. */
2662 dump_generic_ada_node (buffer, t, type, cpp_check, spc, false, true);
2663
2664 if (TREE_CODE (t) == TYPE_DECL)
2665 {
2666 pp_string (buffer, " is ");
2667
2668 if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2669 dump_generic_ada_node
2670 (buffer, TYPE_NAME (orig), type,
2671 cpp_check, spc, false, true);
2672 else
2673 dump_ada_array_type (buffer, t, spc);
2674 }
2675 else
2676 {
2677 tree tmp = TYPE_NAME (TREE_TYPE (t));
2678
2679 if (spc == INDENT_INCR || TREE_STATIC (t))
2680 is_var = 1;
2681
2682 pp_string (buffer, " : ");
2683
2684 if (tmp)
2685 {
2686 if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE
2687 && TREE_CODE (tmp) != INTEGER_TYPE)
2688 pp_string (buffer, "aliased ");
2689
2690 dump_generic_ada_node (buffer, tmp, type, 0, spc, false, true);
2691 }
2692 else
2693 {
2694 pp_string (buffer, "aliased ");
2695
2696 if (!type)
2697 dump_ada_array_type (buffer, t, spc);
2698 else
2699 dump_ada_double_name (buffer, type, t, "_array");
2700 }
2701 }
2702 }
2703 else if (TREE_CODE (t) == FUNCTION_DECL)
2704 {
2705 bool is_function = true, is_method, is_abstract_class = false;
2706 tree decl_name = DECL_NAME (t);
2707 int prev_in_function = in_function;
2708 bool is_abstract = false;
2709 bool is_constructor = false;
2710 bool is_destructor = false;
2711 bool is_copy_constructor = false;
2712
2713 if (!decl_name)
2714 return 0;
2715
2716 if (cpp_check)
2717 {
2718 is_abstract = cpp_check (t, IS_ABSTRACT);
2719 is_constructor = cpp_check (t, IS_CONSTRUCTOR);
2720 is_destructor = cpp_check (t, IS_DESTRUCTOR);
2721 is_copy_constructor = cpp_check (t, IS_COPY_CONSTRUCTOR);
2722 }
2723
2724 /* Skip __comp_dtor destructor which is redundant with the '~class()'
2725 destructor. */
2726 if (is_destructor
2727 && !strncmp (IDENTIFIER_POINTER (decl_name), "__comp", 6))
2728 return 0;
2729
2730 /* Skip copy constructors: some are internal only, and those that are
2731 not cannot be called easily from Ada anyway. */
2732 if (is_copy_constructor)
2733 return 0;
2734
2735 /* If this function has an entry in the dispatch table, we cannot
2736 omit it. */
2737 if (!dump_internal && !DECL_VINDEX (t)
2738 && *IDENTIFIER_POINTER (decl_name) == '_')
2739 {
2740 if (IDENTIFIER_POINTER (decl_name)[1] == '_')
2741 return 0;
2742
2743 INDENT (spc);
2744 pp_string (buffer, "-- skipped func ");
2745 pp_string (buffer, IDENTIFIER_POINTER (decl_name));
2746 return 1;
2747 }
2748
2749 if (need_indent)
2750 INDENT (spc);
2751
2752 if (is_constructor)
2753 pp_string (buffer, "function New_");
2754 else if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
2755 {
2756 is_function = false;
2757 pp_string (buffer, "procedure ");
2758 }
2759 else
2760 pp_string (buffer, "function ");
2761
2762 in_function = is_function;
2763 is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
2764
2765 if (is_destructor)
2766 print_destructor (buffer, t);
2767 else
2768 dump_ada_decl_name (buffer, t, false);
2769
2770 dump_ada_function_declaration
2771 (buffer, t, is_method, is_constructor, is_destructor, spc);
2772 in_function = prev_in_function;
2773
2774 if (is_function)
2775 {
2776 pp_string (buffer, " return ");
2777
2778 if (is_constructor)
2779 {
2780 dump_ada_decl_name (buffer, t, false);
2781 }
2782 else
2783 {
2784 dump_generic_ada_node
2785 (buffer, TREE_TYPE (TREE_TYPE (t)), type, cpp_check,
2786 spc, false, true);
2787 }
2788 }
2789
2790 if (is_constructor && cpp_check && type
2791 && AGGREGATE_TYPE_P (type)
2792 && TYPE_METHODS (type))
2793 {
2794 tree tmp = TYPE_METHODS (type);
2795
2796 for (; tmp; tmp = TREE_CHAIN (tmp))
2797 if (cpp_check (tmp, IS_ABSTRACT))
2798 {
2799 is_abstract_class = 1;
2800 break;
2801 }
2802 }
2803
2804 if (is_abstract || is_abstract_class)
2805 pp_string (buffer, " is abstract");
2806
2807 pp_semicolon (buffer);
2808 pp_string (buffer, " -- ");
2809 dump_sloc (buffer, t);
2810
2811 if (is_abstract)
2812 return 1;
2813
2814 newline_and_indent (buffer, spc);
2815
2816 if (is_constructor)
2817 {
2818 pp_string (buffer, "pragma CPP_Constructor (New_");
2819 dump_ada_decl_name (buffer, t, false);
2820 pp_string (buffer, ", \"");
2821 pp_asm_name (buffer, t);
2822 pp_string (buffer, "\");");
2823 }
2824 else if (is_destructor)
2825 {
2826 pp_string (buffer, "pragma Import (CPP, ");
2827 print_destructor (buffer, t);
2828 pp_string (buffer, ", \"");
2829 pp_asm_name (buffer, t);
2830 pp_string (buffer, "\");");
2831 }
2832 else
2833 {
2834 dump_ada_import (buffer, t);
2835 }
2836
2837 return 1;
2838 }
2839 else if (TREE_CODE (t) == TYPE_DECL && !DECL_ORIGINAL_TYPE (t))
2840 {
2841 int is_interface = 0;
2842 int is_abstract_record = 0;
2843
2844 if (need_indent)
2845 INDENT (spc);
2846
2847 /* Anonymous structs/unions */
2848 dump_generic_ada_node
2849 (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
2850
2851 if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
2852 || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE)
2853 {
2854 pp_string (buffer, " (discr : unsigned := 0)");
2855 }
2856
2857 pp_string (buffer, " is ");
2858
2859 /* Check whether we have an Ada interface compatible class. */
2860 if (cpp_check && AGGREGATE_TYPE_P (TREE_TYPE (t))
2861 && TYPE_METHODS (TREE_TYPE (t)))
2862 {
2863 int num_fields = 0;
2864 tree tmp = TYPE_FIELDS (TREE_TYPE (t));
2865
2866 /* Check that there are no fields other than the virtual table. */
2867 for (; tmp; tmp = TREE_CHAIN (tmp))
2868 {
2869 if (TREE_CODE (tmp) == TYPE_DECL)
2870 continue;
2871 num_fields++;
2872 }
2873
2874 if (num_fields == 1)
2875 is_interface = 1;
2876
2877 /* Also check that there are only virtual methods. */
2878 for (tmp = TYPE_METHODS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
2879 {
2880 if (cpp_check (tmp, IS_ABSTRACT))
2881 is_abstract_record = 1;
2882 else
2883 is_interface = 0;
2884 }
2885 }
2886
2887 if (is_interface)
2888 {
2889 pp_string (buffer, "limited interface; -- ");
2890 dump_sloc (buffer, t);
2891 newline_and_indent (buffer, spc);
2892 pp_string (buffer, "pragma Import (CPP, ");
2893 dump_generic_ada_node
2894 (buffer, TYPE_NAME (TREE_TYPE (t)), type, cpp_check,
2895 spc, false, true);
2896 pp_character (buffer, ')');
2897
2898 print_ada_methods (buffer, TREE_TYPE (t), cpp_check, spc);
2899 }
2900 else
2901 {
2902 if (is_abstract_record)
2903 pp_string (buffer, "abstract ");
2904 dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, false);
2905 }
2906 }
2907 else
2908 {
2909 if (need_indent)
2910 INDENT (spc);
2911
2912 if (TREE_CODE (t) == FIELD_DECL && DECL_NAME (t))
2913 check_name (buffer, t);
2914
2915 /* Print variable/type's name. */
2916 dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, true);
2917
2918 if (TREE_CODE (t) == TYPE_DECL)
2919 {
2920 tree orig = DECL_ORIGINAL_TYPE (t);
2921 int is_subtype = orig && TYPE_NAME (orig) && orig != TREE_TYPE (t);
2922
2923 if (!is_subtype
2924 && (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
2925 || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE))
2926 pp_string (buffer, " (discr : unsigned := 0)");
2927
2928 pp_string (buffer, " is ");
2929
2930 dump_generic_ada_node
2931 (buffer, orig, t, cpp_check, spc, false, is_subtype);
2932 }
2933 else
2934 {
2935 if (spc == INDENT_INCR || TREE_STATIC (t))
2936 is_var = 1;
2937
2938 pp_string (buffer, " : ");
2939
2940 /* Print type declaration. */
2941
2942 if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
2943 && !TYPE_NAME (TREE_TYPE (t)))
2944 {
2945 dump_ada_double_name (buffer, type, t, "_union");
2946 }
2947 else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
2948 {
2949 if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE)
2950 pp_string (buffer, "aliased ");
2951
2952 dump_generic_ada_node
2953 (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
2954 }
2955 else
2956 {
2957 if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
2958 && (TYPE_NAME (TREE_TYPE (t))
2959 || TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE))
2960 pp_string (buffer, "aliased ");
2961
2962 dump_generic_ada_node
2963 (buffer, TREE_TYPE (t), TREE_TYPE (t), cpp_check,
2964 spc, false, true);
2965 }
2966 }
2967 }
2968
2969 if (is_class)
2970 {
2971 spc -= 3;
2972 newline_and_indent (buffer, spc);
2973 pp_string (buffer, "end;");
2974 newline_and_indent (buffer, spc);
2975 pp_string (buffer, "use Class_");
2976 dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
2977 pp_semicolon (buffer);
2978 pp_newline (buffer);
2979
2980 /* All needed indentation/newline performed already, so return 0. */
2981 return 0;
2982 }
2983 else
2984 {
2985 pp_string (buffer, "; -- ");
2986 dump_sloc (buffer, t);
2987 }
2988
2989 if (is_var)
2990 {
2991 newline_and_indent (buffer, spc);
2992 dump_ada_import (buffer, t);
2993 }
2994
2995 return 1;
2996 }
2997
2998 /* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods
2999 with Ada syntax. CPP_CHECK is used to perform C++ queries on nodes. SPC
3000 is the indentation level. If DISPLAY_CONVENTION is true, also print the
3001 pragma Convention for NODE. */
3002
3003 static void
3004 print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
3005 int (*cpp_check)(tree, cpp_operation), int spc,
3006 bool display_convention)
3007 {
3008 tree tmp;
3009 int is_union =
3010 TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
3011 char buf [16];
3012 int field_num = 0;
3013 int field_spc = spc + INDENT_INCR;
3014 int need_semicolon;
3015
3016 bitfield_used = false;
3017
3018 if (!TYPE_FIELDS (node))
3019 pp_string (buffer, "null record;");
3020 else
3021 {
3022 pp_string (buffer, "record");
3023
3024 /* Print the contents of the structure. */
3025
3026 if (is_union)
3027 {
3028 newline_and_indent (buffer, spc + INDENT_INCR);
3029 pp_string (buffer, "case discr is");
3030 field_spc = spc + INDENT_INCR * 3;
3031 }
3032
3033 pp_newline (buffer);
3034
3035 /* Print the non-static fields of the structure. */
3036 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3037 {
3038 /* Add parent field if needed. */
3039 if (!DECL_NAME (tmp))
3040 {
3041 if (!is_tagged_type (TREE_TYPE (tmp)))
3042 {
3043 if (!TYPE_NAME (TREE_TYPE (tmp)))
3044 print_ada_declaration
3045 (buffer, tmp, type, cpp_check, field_spc);
3046 else
3047 {
3048 INDENT (field_spc);
3049
3050 if (field_num == 0)
3051 pp_string (buffer, "parent : ");
3052 else
3053 {
3054 sprintf (buf, "field_%d : ", field_num + 1);
3055 pp_string (buffer, buf);
3056 }
3057 dump_ada_decl_name
3058 (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
3059 pp_semicolon (buffer);
3060 }
3061 pp_newline (buffer);
3062 field_num++;
3063 }
3064 }
3065 /* Avoid printing the structure recursively. */
3066 else if ((TREE_TYPE (tmp) != node
3067 || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
3068 && TREE_TYPE (TREE_TYPE (tmp)) != node))
3069 && TREE_CODE (tmp) != TYPE_DECL
3070 && !TREE_STATIC (tmp))
3071 {
3072 /* Skip internal virtual table field. */
3073 if (strncmp (IDENTIFIER_POINTER (DECL_NAME (tmp)), "_vptr", 5))
3074 {
3075 if (is_union)
3076 {
3077 if (TREE_CHAIN (tmp)
3078 && TREE_TYPE (TREE_CHAIN (tmp)) != node
3079 && TREE_CODE (TREE_CHAIN (tmp)) != TYPE_DECL)
3080 sprintf (buf, "when %d =>", field_num);
3081 else
3082 sprintf (buf, "when others =>");
3083
3084 INDENT (spc + INDENT_INCR * 2);
3085 pp_string (buffer, buf);
3086 pp_newline (buffer);
3087 }
3088
3089 if (print_ada_declaration (buffer,
3090 tmp, type, cpp_check, field_spc))
3091 {
3092 pp_newline (buffer);
3093 field_num++;
3094 }
3095 }
3096 }
3097 }
3098
3099 if (is_union)
3100 {
3101 INDENT (spc + INDENT_INCR);
3102 pp_string (buffer, "end case;");
3103 pp_newline (buffer);
3104 }
3105
3106 if (field_num == 0)
3107 {
3108 INDENT (spc + INDENT_INCR);
3109 pp_string (buffer, "null;");
3110 pp_newline (buffer);
3111 }
3112
3113 INDENT (spc);
3114 pp_string (buffer, "end record;");
3115 }
3116
3117 newline_and_indent (buffer, spc);
3118
3119 if (!display_convention)
3120 return;
3121
3122 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
3123 {
3124 if (TYPE_METHODS (TREE_TYPE (type)))
3125 pp_string (buffer, "pragma Import (CPP, ");
3126 else
3127 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
3128 }
3129 else
3130 pp_string (buffer, "pragma Convention (C, ");
3131
3132 package_prefix = false;
3133 dump_generic_ada_node
3134 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3135 package_prefix = true;
3136 pp_character (buffer, ')');
3137
3138 if (is_union)
3139 {
3140 pp_semicolon (buffer);
3141 newline_and_indent (buffer, spc);
3142 pp_string (buffer, "pragma Unchecked_Union (");
3143
3144 dump_generic_ada_node
3145 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3146 pp_character (buffer, ')');
3147 }
3148
3149 if (bitfield_used)
3150 {
3151 pp_semicolon (buffer);
3152 newline_and_indent (buffer, spc);
3153 pp_string (buffer, "pragma Pack (");
3154 dump_generic_ada_node
3155 (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
3156 pp_character (buffer, ')');
3157 bitfield_used = false;
3158 }
3159
3160 print_ada_methods (buffer, node, cpp_check, spc);
3161
3162 /* Print the static fields of the structure, if any. */
3163 need_semicolon = TYPE_METHODS (node) == NULL_TREE;
3164 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3165 {
3166 if (DECL_NAME (tmp) && TREE_STATIC (tmp))
3167 {
3168 if (need_semicolon)
3169 {
3170 need_semicolon = false;
3171 pp_semicolon (buffer);
3172 }
3173 pp_newline (buffer);
3174 pp_newline (buffer);
3175 print_ada_declaration (buffer, tmp, type, cpp_check, spc);
3176 }
3177 }
3178 }
3179
3180 /* Dump all the declarations in SOURCE_FILE to an Ada spec.
3181 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
3182 nodes for SOURCE_FILE. CPP_CHECK is used to perform C++ queries on
3183 nodes. */
3184
3185 static void
3186 dump_ads (const char *source_file,
3187 void (*collect_all_refs)(const char *),
3188 int (*cpp_check)(tree, cpp_operation))
3189 {
3190 char *ads_name;
3191 char *pkg_name;
3192 char *s;
3193 FILE *f;
3194
3195 pkg_name = get_ada_package (source_file);
3196
3197 /* Construct the the .ads filename and package name. */
3198 ads_name = xstrdup (pkg_name);
3199
3200 for (s = ads_name; *s; s++)
3201 *s = TOLOWER (*s);
3202
3203 ads_name = reconcat (ads_name, ads_name, ".ads", NULL);
3204
3205 /* Write out the .ads file. */
3206 f = fopen (ads_name, "w");
3207 if (f)
3208 {
3209 pretty_printer pp;
3210
3211 pp_construct (&pp, NULL, 0);
3212 pp_needs_newline (&pp) = true;
3213 pp.buffer->stream = f;
3214
3215 /* Dump all relevant macros. */
3216 dump_ada_macros (&pp, source_file);
3217
3218 /* Reset the table of withs for this file. */
3219 reset_ada_withs ();
3220
3221 (*collect_all_refs) (source_file);
3222
3223 /* Dump all references. */
3224 dump_ada_nodes (&pp, source_file, cpp_check);
3225
3226 /* Dump withs. */
3227 dump_ada_withs (f);
3228
3229 fprintf (f, "\npackage %s is\n\n", pkg_name);
3230 pp_write_text_to_stream (&pp);
3231 /* ??? need to free pp */
3232 fprintf (f, "end %s;\n", pkg_name);
3233 fclose (f);
3234 }
3235
3236 free (ads_name);
3237 free (pkg_name);
3238 }
3239
3240 static const char **source_refs = NULL;
3241 static int source_refs_used = 0;
3242 static int source_refs_allocd = 0;
3243
3244 /* Add an entry for FILENAME to the table SOURCE_REFS. */
3245
3246 void
3247 collect_source_ref (const char *filename)
3248 {
3249 int i;
3250
3251 if (!filename)
3252 return;
3253
3254 if (source_refs_allocd == 0)
3255 {
3256 source_refs_allocd = 1024;
3257 source_refs = XNEWVEC (const char *, source_refs_allocd);
3258 }
3259
3260 for (i = 0; i < source_refs_used; i++)
3261 if (filename == source_refs [i])
3262 return;
3263
3264 if (source_refs_used == source_refs_allocd)
3265 {
3266 source_refs_allocd *= 2;
3267 source_refs = XRESIZEVEC (const char *, source_refs, source_refs_allocd);
3268 }
3269
3270 source_refs [source_refs_used++] = filename;
3271 }
3272
3273 /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
3274 using callbacks COLLECT_ALL_REFS and CPP_CHECK.
3275 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
3276 nodes for a given source file.
3277 CPP_CHECK is used to perform C++ queries on nodes, or NULL for the C
3278 front-end. */
3279
3280 void
3281 dump_ada_specs (void (*collect_all_refs)(const char *),
3282 int (*cpp_check)(tree, cpp_operation))
3283 {
3284 int i;
3285
3286 /* Iterate over the list of files to dump specs for */
3287 for (i = 0; i < source_refs_used; i++)
3288 dump_ads (source_refs [i], collect_all_refs, cpp_check);
3289
3290 /* Free files table. */
3291 free (source_refs);
3292 }