OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [c-family/] [c-ada-spec.c] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.