OSDN Git Service

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