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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [xr_tabls.adb] - Blame information for rev 713

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

Line No. Rev Author Line
1 706 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                             X R  _ T A B L S                             --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1998-2010, Free Software Foundation, Inc.         --
10
--                                                                          --
11
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
12
-- terms of the  GNU General Public License as published  by the Free Soft- --
13
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17
-- for  more details.  You should have  received  a copy of the GNU General --
18
-- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
19
-- http://www.gnu.org/licenses for a complete copy of the license.          --
20
--                                                                          --
21
-- GNAT was originally developed  by the GNAT team at  New York University. --
22
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
23
--                                                                          --
24
------------------------------------------------------------------------------
25
 
26
with Types;    use Types;
27
with Osint;
28
with Hostparm;
29
 
30
with Ada.Unchecked_Conversion;
31
with Ada.Unchecked_Deallocation;
32
with Ada.Strings.Fixed;
33
with Ada.Strings;
34
with Ada.Text_IO;
35
with Ada.Characters.Handling;   use Ada.Characters.Handling;
36
with Ada.Strings.Unbounded;     use Ada.Strings.Unbounded;
37
 
38
with GNAT.OS_Lib;               use GNAT.OS_Lib;
39
with GNAT.Directory_Operations; use GNAT.Directory_Operations;
40
with GNAT.HTable;               use GNAT.HTable;
41
with GNAT.Heap_Sort_G;
42
 
43
package body Xr_Tabls is
44
 
45
   type HTable_Headers is range 1 .. 10000;
46
 
47
   procedure Set_Next (E : File_Reference; Next : File_Reference);
48
   function  Next (E : File_Reference) return File_Reference;
49
   function  Get_Key (E : File_Reference) return Cst_String_Access;
50
   function  Hash (F : Cst_String_Access) return HTable_Headers;
51
   function  Equal (F1, F2 : Cst_String_Access) return Boolean;
52
   --  The five subprograms above are used to instantiate the static
53
   --  htable to store the files that should be processed.
54
 
55
   package File_HTable is new GNAT.HTable.Static_HTable
56
     (Header_Num => HTable_Headers,
57
      Element    => File_Record,
58
      Elmt_Ptr   => File_Reference,
59
      Null_Ptr   => null,
60
      Set_Next   => Set_Next,
61
      Next       => Next,
62
      Key        => Cst_String_Access,
63
      Get_Key    => Get_Key,
64
      Hash       => Hash,
65
      Equal      => Equal);
66
   --  A hash table to store all the files referenced in the
67
   --  application.  The keys in this htable are the name of the files
68
   --  themselves, therefore it is assumed that the source path
69
   --  doesn't contain twice the same source or ALI file name
70
 
71
   type Unvisited_Files_Record;
72
   type Unvisited_Files_Access is access Unvisited_Files_Record;
73
   type Unvisited_Files_Record is record
74
      File : File_Reference;
75
      Next : Unvisited_Files_Access;
76
   end record;
77
   --  A special list, in addition to File_HTable, that only stores
78
   --  the files that haven't been visited so far. Note that the File
79
   --  list points to some data in File_HTable, and thus should never be freed.
80
 
81
   function Next (E : Declaration_Reference) return Declaration_Reference;
82
   procedure Set_Next (E, Next : Declaration_Reference);
83
   function  Get_Key (E : Declaration_Reference) return Cst_String_Access;
84
   --  The subprograms above are used to instantiate the static
85
   --  htable to store the entities that have been found in the application
86
 
87
   package Entities_HTable is new GNAT.HTable.Static_HTable
88
     (Header_Num => HTable_Headers,
89
      Element    => Declaration_Record,
90
      Elmt_Ptr   => Declaration_Reference,
91
      Null_Ptr   => null,
92
      Set_Next   => Set_Next,
93
      Next       => Next,
94
      Key        => Cst_String_Access,
95
      Get_Key    => Get_Key,
96
      Hash       => Hash,
97
      Equal      => Equal);
98
   --  A hash table to store all the entities defined in the
99
   --  application. For each entity, we store a list of its reference
100
   --  locations as well.
101
   --  The keys in this htable should be created with Key_From_Ref,
102
   --  and are the file, line and column of the declaration, which are
103
   --  unique for every entity.
104
 
105
   Entities_Count : Natural := 0;
106
   --  Number of entities in Entities_HTable. This is used in the end
107
   --  when sorting the table.
108
 
109
   Longest_File_Name_In_Table : Natural := 0;
110
   Unvisited_Files            : Unvisited_Files_Access := null;
111
   Directories                : Project_File_Ptr;
112
   Default_Match              : Boolean := False;
113
   --  The above need commenting ???
114
 
115
   function Parse_Gnatls_Src return String;
116
   --  Return the standard source directories (taking into account the
117
   --  ADA_INCLUDE_PATH environment variable, if Osint.Add_Default_Search_Dirs
118
   --  was called first).
119
 
120
   function Parse_Gnatls_Obj return String;
121
   --  Return the standard object directories (taking into account the
122
   --  ADA_OBJECTS_PATH environment variable).
123
 
124
   function Key_From_Ref
125
     (File_Ref  : File_Reference;
126
      Line      : Natural;
127
      Column    : Natural)
128
      return      String;
129
   --  Return a key for the symbol declared at File_Ref, Line,
130
   --  Column. This key should be used for lookup in Entity_HTable
131
 
132
   function Is_Less_Than (Decl1, Decl2 : Declaration_Reference) return Boolean;
133
   --  Compare two declarations (the comparison is case-insensitive)
134
 
135
   function Is_Less_Than (Ref1, Ref2 : Reference) return Boolean;
136
   --  Compare two references
137
 
138
   procedure Store_References
139
     (Decl            : Declaration_Reference;
140
      Get_Writes      : Boolean := False;
141
      Get_Reads       : Boolean := False;
142
      Get_Bodies      : Boolean := False;
143
      Get_Declaration : Boolean := False;
144
      Arr             : in out Reference_Array;
145
      Index           : in out Natural);
146
   --  Store in Arr, starting at Index, all the references to Decl. The Get_*
147
   --  parameters can be used to indicate which references should be stored.
148
   --  Constraint_Error will be raised if Arr is not big enough.
149
 
150
   procedure Sort (Arr : in out Reference_Array);
151
   --  Sort an array of references (Arr'First must be 1)
152
 
153
   --------------
154
   -- Set_Next --
155
   --------------
156
 
157
   procedure Set_Next (E : File_Reference; Next : File_Reference) is
158
   begin
159
      E.Next := Next;
160
   end Set_Next;
161
 
162
   procedure Set_Next
163
     (E : Declaration_Reference; Next : Declaration_Reference) is
164
   begin
165
      E.Next := Next;
166
   end Set_Next;
167
 
168
   -------------
169
   -- Get_Key --
170
   -------------
171
 
172
   function Get_Key (E : File_Reference) return Cst_String_Access is
173
   begin
174
      return E.File;
175
   end Get_Key;
176
 
177
   function Get_Key (E : Declaration_Reference) return Cst_String_Access is
178
   begin
179
      return E.Key;
180
   end Get_Key;
181
 
182
   ----------
183
   -- Hash --
184
   ----------
185
 
186
   function Hash (F : Cst_String_Access) return HTable_Headers is
187
      function H is new GNAT.HTable.Hash (HTable_Headers);
188
 
189
   begin
190
      return H (F.all);
191
   end Hash;
192
 
193
   -----------
194
   -- Equal --
195
   -----------
196
 
197
   function Equal (F1, F2 : Cst_String_Access) return Boolean is
198
   begin
199
      return F1.all = F2.all;
200
   end Equal;
201
 
202
   ------------------
203
   -- Key_From_Ref --
204
   ------------------
205
 
206
   function Key_From_Ref
207
     (File_Ref : File_Reference;
208
      Line     : Natural;
209
      Column   : Natural)
210
      return     String
211
   is
212
   begin
213
      return File_Ref.File.all & Natural'Image (Line) & Natural'Image (Column);
214
   end Key_From_Ref;
215
 
216
   ---------------------
217
   -- Add_Declaration --
218
   ---------------------
219
 
220
   function Add_Declaration
221
     (File_Ref     : File_Reference;
222
      Symbol       : String;
223
      Line         : Natural;
224
      Column       : Natural;
225
      Decl_Type    : Character;
226
      Remove_Only  : Boolean := False;
227
      Symbol_Match : Boolean := True)
228
      return         Declaration_Reference
229
   is
230
      procedure Unchecked_Free is new Ada.Unchecked_Deallocation
231
        (Declaration_Record, Declaration_Reference);
232
 
233
      Key : aliased constant String := Key_From_Ref (File_Ref, Line, Column);
234
 
235
      New_Decl : Declaration_Reference :=
236
                   Entities_HTable.Get (Key'Unchecked_Access);
237
 
238
      Is_Parameter : Boolean := False;
239
 
240
   begin
241
      --  Insert the Declaration in the table. There might already be a
242
      --  declaration in the table if the entity is a parameter, so we
243
      --  need to check that first.
244
 
245
      if New_Decl /= null and then New_Decl.Symbol_Length = 0 then
246
         Is_Parameter := New_Decl.Is_Parameter;
247
         Entities_HTable.Remove (Key'Unrestricted_Access);
248
         Entities_Count := Entities_Count - 1;
249
         Free (New_Decl.Key);
250
         Unchecked_Free (New_Decl);
251
         New_Decl := null;
252
      end if;
253
 
254
      --  The declaration might also already be there for parent types. In
255
      --  this case, we should keep the entry, since some other entries are
256
      --  pointing to it.
257
 
258
      if New_Decl = null
259
        and then not Remove_Only
260
      then
261
         New_Decl :=
262
           new Declaration_Record'
263
             (Symbol_Length => Symbol'Length,
264
              Symbol        => Symbol,
265
              Key           => new String'(Key),
266
              Decl          => new Reference_Record'
267
                                     (File          => File_Ref,
268
                                      Line          => Line,
269
                                      Column        => Column,
270
                                      Source_Line   => null,
271
                                      Next          => null),
272
              Is_Parameter  => Is_Parameter,
273
              Decl_Type     => Decl_Type,
274
              Body_Ref      => null,
275
              Ref_Ref       => null,
276
              Modif_Ref     => null,
277
              Match         => Symbol_Match
278
                                 and then
279
                                   (Default_Match
280
                                     or else Match (File_Ref, Line, Column)),
281
              Par_Symbol    => null,
282
              Next          => null);
283
 
284
         Entities_HTable.Set (New_Decl);
285
         Entities_Count := Entities_Count + 1;
286
 
287
         if New_Decl.Match then
288
            Longest_File_Name_In_Table :=
289
              Natural'Max (File_Ref.File'Length, Longest_File_Name_In_Table);
290
         end if;
291
 
292
      elsif New_Decl /= null
293
        and then not New_Decl.Match
294
      then
295
         New_Decl.Match := Default_Match
296
           or else Match (File_Ref, Line, Column);
297
      end if;
298
 
299
      return New_Decl;
300
   end Add_Declaration;
301
 
302
   ----------------------
303
   -- Add_To_Xref_File --
304
   ----------------------
305
 
306
   function Add_To_Xref_File
307
     (File_Name       : String;
308
      Visited         : Boolean := True;
309
      Emit_Warning    : Boolean := False;
310
      Gnatchop_File   : String  := "";
311
      Gnatchop_Offset : Integer := 0) return File_Reference
312
   is
313
      Base    : aliased constant String := Base_Name (File_Name);
314
      Dir     : constant String := Dir_Name (File_Name);
315
      Dir_Acc : GNAT.OS_Lib.String_Access   := null;
316
      Ref     : File_Reference;
317
 
318
   begin
319
      --  Do we have a directory name as well?
320
 
321
      if File_Name /= Base then
322
         Dir_Acc := new String'(Dir);
323
      end if;
324
 
325
      Ref := File_HTable.Get (Base'Unchecked_Access);
326
      if Ref = null then
327
         Ref := new File_Record'
328
           (File            => new String'(Base),
329
            Dir             => Dir_Acc,
330
            Lines           => null,
331
            Visited         => Visited,
332
            Emit_Warning    => Emit_Warning,
333
            Gnatchop_File   => new String'(Gnatchop_File),
334
            Gnatchop_Offset => Gnatchop_Offset,
335
            Next            => null);
336
         File_HTable.Set (Ref);
337
 
338
         if not Visited then
339
 
340
            --  Keep a separate list for faster access
341
 
342
            Set_Unvisited (Ref);
343
         end if;
344
      end if;
345
      return Ref;
346
   end Add_To_Xref_File;
347
 
348
   --------------
349
   -- Add_Line --
350
   --------------
351
 
352
   procedure Add_Line
353
     (File   : File_Reference;
354
      Line   : Natural;
355
      Column : Natural)
356
   is
357
   begin
358
      File.Lines := new Ref_In_File'(Line   => Line,
359
                                     Column => Column,
360
                                     Next   => File.Lines);
361
   end Add_Line;
362
 
363
   ----------------
364
   -- Add_Parent --
365
   ----------------
366
 
367
   procedure Add_Parent
368
     (Declaration : in out Declaration_Reference;
369
      Symbol      : String;
370
      Line        : Natural;
371
      Column      : Natural;
372
      File_Ref    : File_Reference)
373
   is
374
   begin
375
      Declaration.Par_Symbol :=
376
        Add_Declaration
377
          (File_Ref, Symbol, Line, Column,
378
           Decl_Type    => ' ',
379
           Symbol_Match => False);
380
   end Add_Parent;
381
 
382
   -------------------
383
   -- Add_Reference --
384
   -------------------
385
 
386
   procedure Add_Reference
387
     (Declaration   : Declaration_Reference;
388
      File_Ref      : File_Reference;
389
      Line          : Natural;
390
      Column        : Natural;
391
      Ref_Type      : Character;
392
      Labels_As_Ref : Boolean)
393
   is
394
      New_Ref : Reference;
395
 
396
   begin
397
      case Ref_Type is
398
         when 'b' | 'c' | 'H' | 'm' | 'o' | 'r' | 'R' |
399
              's' | 'i' | ' ' | 'x' =>
400
            null;
401
 
402
         when 'l' | 'w' =>
403
            if not Labels_As_Ref then
404
               return;
405
            end if;
406
 
407
         when '=' | '<' | '>' | '^' =>
408
 
409
            --  Create a dummy declaration in the table to report it as a
410
            --  parameter. Note that the current declaration for the subprogram
411
            --  comes before the declaration of the parameter.
412
 
413
            declare
414
               Key      : constant String :=
415
                            Key_From_Ref (File_Ref, Line, Column);
416
               New_Decl : Declaration_Reference;
417
 
418
            begin
419
               New_Decl := new Declaration_Record'
420
                 (Symbol_Length => 0,
421
                  Symbol        => "",
422
                  Key           => new String'(Key),
423
                  Decl          => new Reference_Record'
424
                                     (File          => File_Ref,
425
                                      Line          => Line,
426
                                      Column        => Column,
427
                                      Source_Line   => null,
428
                                      Next          => null),
429
                  Is_Parameter  => True,
430
                  Decl_Type     => ' ',
431
                  Body_Ref      => null,
432
                  Ref_Ref       => null,
433
                  Modif_Ref     => null,
434
                  Match         => False,
435
                  Par_Symbol    => null,
436
                  Next          => null);
437
               Entities_HTable.Set (New_Decl);
438
               Entities_Count := Entities_Count + 1;
439
            end;
440
 
441
         when 'e' | 'z' | 't' | 'p' | 'P' | 'k' | 'd' =>
442
            return;
443
 
444
         when others    =>
445
            Ada.Text_IO.Put_Line ("Unknown reference type: " & Ref_Type);
446
            return;
447
      end case;
448
 
449
      New_Ref := new Reference_Record'
450
        (File        => File_Ref,
451
         Line        => Line,
452
         Column      => Column,
453
         Source_Line => null,
454
         Next        => null);
455
 
456
      --  We can insert the reference into the list directly, since all the
457
      --  references will appear only once in the ALI file corresponding to the
458
      --  file where they are referenced. This saves a lot of time compared to
459
      --  checking the list to check if it exists.
460
 
461
      case Ref_Type is
462
         when 'b' | 'c' =>
463
            New_Ref.Next          := Declaration.Body_Ref;
464
            Declaration.Body_Ref  := New_Ref;
465
 
466
         when 'r' | 'R' | 's' | 'H' | 'i' | 'l' | 'o' | ' ' | 'x' | 'w' =>
467
            New_Ref.Next          := Declaration.Ref_Ref;
468
            Declaration.Ref_Ref   := New_Ref;
469
 
470
         when 'm' =>
471
            New_Ref.Next          := Declaration.Modif_Ref;
472
            Declaration.Modif_Ref := New_Ref;
473
 
474
         when others =>
475
            null;
476
      end case;
477
 
478
      if not Declaration.Match then
479
         Declaration.Match := Match (File_Ref, Line, Column);
480
      end if;
481
 
482
      if Declaration.Match then
483
         Longest_File_Name_In_Table :=
484
           Natural'Max (File_Ref.File'Length, Longest_File_Name_In_Table);
485
      end if;
486
   end Add_Reference;
487
 
488
   -------------------
489
   -- ALI_File_Name --
490
   -------------------
491
 
492
   function ALI_File_Name (Ada_File_Name : String) return String is
493
 
494
      --  ??? Should ideally be based on the naming scheme defined in
495
      --  project files.
496
 
497
      Index : constant Natural :=
498
                Ada.Strings.Fixed.Index
499
                  (Ada_File_Name, ".", Going => Ada.Strings.Backward);
500
 
501
   begin
502
      if Index /= 0 then
503
         return Ada_File_Name (Ada_File_Name'First .. Index)
504
           & Osint.ALI_Suffix.all;
505
      else
506
         return Ada_File_Name & "." & Osint.ALI_Suffix.all;
507
      end if;
508
   end ALI_File_Name;
509
 
510
   ------------------
511
   -- Is_Less_Than --
512
   ------------------
513
 
514
   function Is_Less_Than (Ref1, Ref2 : Reference) return Boolean is
515
   begin
516
      if Ref1 = null then
517
         return False;
518
      elsif Ref2 = null then
519
         return True;
520
      end if;
521
 
522
      if Ref1.File.File.all < Ref2.File.File.all then
523
         return True;
524
 
525
      elsif Ref1.File.File.all = Ref2.File.File.all then
526
         return (Ref1.Line < Ref2.Line
527
                 or else (Ref1.Line = Ref2.Line
528
                          and then Ref1.Column < Ref2.Column));
529
      end if;
530
 
531
      return False;
532
   end Is_Less_Than;
533
 
534
   ------------------
535
   -- Is_Less_Than --
536
   ------------------
537
 
538
   function Is_Less_Than (Decl1, Decl2 : Declaration_Reference) return Boolean
539
   is
540
      --  We cannot store the data case-insensitive in the table,
541
      --  since we wouldn't be able to find the right casing for the
542
      --  display later on.
543
 
544
      S1 : constant String := To_Lower (Decl1.Symbol);
545
      S2 : constant String := To_Lower (Decl2.Symbol);
546
 
547
   begin
548
      if S1 < S2 then
549
         return True;
550
      elsif S1 > S2 then
551
         return False;
552
      end if;
553
 
554
      return Decl1.Key.all < Decl2.Key.all;
555
   end Is_Less_Than;
556
 
557
   -------------------------
558
   -- Create_Project_File --
559
   -------------------------
560
 
561
   procedure Create_Project_File (Name : String) is
562
      Obj_Dir     : Unbounded_String := Null_Unbounded_String;
563
      Src_Dir     : Unbounded_String := Null_Unbounded_String;
564
      Build_Dir   : GNAT.OS_Lib.String_Access := new String'("");
565
 
566
      F           : File_Descriptor;
567
      Len         : Positive;
568
      File_Name   : aliased String := Name & ASCII.NUL;
569
 
570
   begin
571
      --  Read the size of the file
572
 
573
      F := Open_Read (File_Name'Address, Text);
574
 
575
      --  Project file not found
576
 
577
      if F /= Invalid_FD then
578
         Len := Positive (File_Length (F));
579
 
580
         declare
581
            Buffer : String (1 .. Len);
582
            Index  : Positive := Buffer'First;
583
            Last   : Positive;
584
 
585
         begin
586
            Len := Read (F, Buffer'Address, Len);
587
            Close (F);
588
 
589
            --  First, look for Build_Dir, since all the source and object
590
            --  path are relative to it.
591
 
592
            while Index <= Buffer'Last loop
593
 
594
               --  Find the end of line
595
 
596
               Last := Index;
597
               while Last <= Buffer'Last
598
                 and then Buffer (Last) /= ASCII.LF
599
                 and then Buffer (Last) /= ASCII.CR
600
               loop
601
                  Last := Last + 1;
602
               end loop;
603
 
604
               if Index <= Buffer'Last - 9
605
                 and then Buffer (Index .. Index + 9) = "build_dir="
606
               then
607
                  Index := Index + 10;
608
                  while Index <= Last
609
                    and then (Buffer (Index) = ' '
610
                              or else Buffer (Index) = ASCII.HT)
611
                  loop
612
                     Index := Index + 1;
613
                  end loop;
614
 
615
                  Free (Build_Dir);
616
                  Build_Dir := new String'(Buffer (Index .. Last - 1));
617
               end if;
618
 
619
               Index := Last + 1;
620
 
621
               --  In case we had a ASCII.CR/ASCII.LF end of line, skip the
622
               --  remaining symbol
623
 
624
               if Index <= Buffer'Last
625
                 and then Buffer (Index) = ASCII.LF
626
               then
627
                  Index := Index + 1;
628
               end if;
629
            end loop;
630
 
631
            --  Now parse the source and object paths
632
 
633
            Index := Buffer'First;
634
            while Index <= Buffer'Last loop
635
 
636
               --  Find the end of line
637
 
638
               Last := Index;
639
               while Last <= Buffer'Last
640
                 and then Buffer (Last) /= ASCII.LF
641
                 and then Buffer (Last) /= ASCII.CR
642
               loop
643
                  Last := Last + 1;
644
               end loop;
645
 
646
               if Index <= Buffer'Last - 7
647
                 and then Buffer (Index .. Index + 7) = "src_dir="
648
               then
649
                  Append (Src_Dir, Normalize_Pathname
650
                          (Name      => Ada.Strings.Fixed.Trim
651
                           (Buffer (Index + 8 .. Last - 1), Ada.Strings.Both),
652
                           Directory => Build_Dir.all) & Path_Separator);
653
 
654
               elsif Index <= Buffer'Last - 7
655
                 and then Buffer (Index .. Index + 7) = "obj_dir="
656
               then
657
                  Append (Obj_Dir, Normalize_Pathname
658
                          (Name      => Ada.Strings.Fixed.Trim
659
                           (Buffer (Index + 8 .. Last - 1), Ada.Strings.Both),
660
                           Directory => Build_Dir.all) & Path_Separator);
661
               end if;
662
 
663
               --  In case we had a ASCII.CR/ASCII.LF end of line, skip the
664
               --  remaining symbol
665
               Index := Last + 1;
666
 
667
               if Index <= Buffer'Last
668
                 and then Buffer (Index) = ASCII.LF
669
               then
670
                  Index := Index + 1;
671
               end if;
672
            end loop;
673
         end;
674
      end if;
675
 
676
      Osint.Add_Default_Search_Dirs;
677
 
678
      declare
679
         Src : constant String := Parse_Gnatls_Src;
680
         Obj : constant String := Parse_Gnatls_Obj;
681
 
682
      begin
683
         Directories := new Project_File'
684
           (Src_Dir_Length     => Length (Src_Dir) + Src'Length,
685
            Obj_Dir_Length     => Length (Obj_Dir) + Obj'Length,
686
            Src_Dir            => To_String (Src_Dir) & Src,
687
            Obj_Dir            => To_String (Obj_Dir) & Obj,
688
            Src_Dir_Index      => 1,
689
            Obj_Dir_Index      => 1,
690
            Last_Obj_Dir_Start => 0);
691
      end;
692
 
693
      Free (Build_Dir);
694
   end Create_Project_File;
695
 
696
   ---------------------
697
   -- Current_Obj_Dir --
698
   ---------------------
699
 
700
   function Current_Obj_Dir return String is
701
   begin
702
      return Directories.Obj_Dir
703
        (Directories.Last_Obj_Dir_Start .. Directories.Obj_Dir_Index - 2);
704
   end Current_Obj_Dir;
705
 
706
   ----------------
707
   -- Get_Column --
708
   ----------------
709
 
710
   function Get_Column (Decl : Declaration_Reference) return String is
711
   begin
712
      return Ada.Strings.Fixed.Trim (Natural'Image (Decl.Decl.Column),
713
                                     Ada.Strings.Left);
714
   end Get_Column;
715
 
716
   function Get_Column (Ref : Reference) return String is
717
   begin
718
      return Ada.Strings.Fixed.Trim (Natural'Image (Ref.Column),
719
                                     Ada.Strings.Left);
720
   end Get_Column;
721
 
722
   ---------------------
723
   -- Get_Declaration --
724
   ---------------------
725
 
726
   function Get_Declaration
727
     (File_Ref : File_Reference;
728
      Line     : Natural;
729
      Column   : Natural)
730
      return     Declaration_Reference
731
   is
732
      Key : aliased constant String := Key_From_Ref (File_Ref, Line, Column);
733
 
734
   begin
735
      return Entities_HTable.Get (Key'Unchecked_Access);
736
   end Get_Declaration;
737
 
738
   ----------------------
739
   -- Get_Emit_Warning --
740
   ----------------------
741
 
742
   function Get_Emit_Warning (File : File_Reference) return Boolean is
743
   begin
744
      return File.Emit_Warning;
745
   end Get_Emit_Warning;
746
 
747
   --------------
748
   -- Get_File --
749
   --------------
750
 
751
   function Get_File
752
     (Decl     : Declaration_Reference;
753
      With_Dir : Boolean := False) return String
754
   is
755
   begin
756
      return Get_File (Decl.Decl.File, With_Dir);
757
   end Get_File;
758
 
759
   function Get_File
760
     (Ref      : Reference;
761
      With_Dir : Boolean := False) return String
762
   is
763
   begin
764
      return Get_File (Ref.File, With_Dir);
765
   end Get_File;
766
 
767
   function Get_File
768
     (File     : File_Reference;
769
      With_Dir : Boolean := False;
770
      Strip    : Natural    := 0) return String
771
   is
772
      Tmp : GNAT.OS_Lib.String_Access;
773
 
774
      function Internal_Strip (Full_Name : String) return String;
775
      --  Internal function to process the Strip parameter
776
 
777
      --------------------
778
      -- Internal_Strip --
779
      --------------------
780
 
781
      function Internal_Strip (Full_Name : String) return String is
782
         Unit_End        : Natural;
783
         Extension_Start : Natural;
784
         S               : Natural;
785
 
786
      begin
787
         if Strip = 0 then
788
            return Full_Name;
789
         end if;
790
 
791
         --  Isolate the file extension
792
 
793
         Extension_Start := Full_Name'Last;
794
         while Extension_Start >= Full_Name'First
795
           and then Full_Name (Extension_Start) /= '.'
796
         loop
797
            Extension_Start := Extension_Start - 1;
798
         end loop;
799
 
800
         --  Strip the right number of subunit_names
801
 
802
         S := Strip;
803
         Unit_End := Extension_Start - 1;
804
         while Unit_End >= Full_Name'First
805
           and then S > 0
806
         loop
807
            if Full_Name (Unit_End) = '-' then
808
               S := S - 1;
809
            end if;
810
 
811
            Unit_End := Unit_End - 1;
812
         end loop;
813
 
814
         if Unit_End < Full_Name'First then
815
            return "";
816
         else
817
            return Full_Name (Full_Name'First .. Unit_End)
818
              & Full_Name (Extension_Start .. Full_Name'Last);
819
         end if;
820
      end Internal_Strip;
821
 
822
   --  Start of processing for Get_File;
823
 
824
   begin
825
      --  If we do not want the full path name
826
 
827
      if not With_Dir then
828
         return Internal_Strip (File.File.all);
829
      end if;
830
 
831
      if File.Dir = null then
832
         if Ada.Strings.Fixed.Tail (File.File.all, 3) =
833
                                               Osint.ALI_Suffix.all
834
         then
835
            Tmp := Locate_Regular_File
836
                     (Internal_Strip (File.File.all), Directories.Obj_Dir);
837
         else
838
            Tmp := Locate_Regular_File
839
                     (File.File.all, Directories.Src_Dir);
840
         end if;
841
 
842
         if Tmp = null then
843
            File.Dir := new String'("");
844
         else
845
            File.Dir := new String'(Dir_Name (Tmp.all));
846
            Free (Tmp);
847
         end if;
848
      end if;
849
 
850
      return Internal_Strip (File.Dir.all & File.File.all);
851
   end Get_File;
852
 
853
   ------------------
854
   -- Get_File_Ref --
855
   ------------------
856
 
857
   function Get_File_Ref (Ref : Reference) return File_Reference is
858
   begin
859
      return Ref.File;
860
   end Get_File_Ref;
861
 
862
   -----------------------
863
   -- Get_Gnatchop_File --
864
   -----------------------
865
 
866
   function Get_Gnatchop_File
867
     (File     : File_Reference;
868
      With_Dir : Boolean := False)
869
      return     String
870
   is
871
   begin
872
      if File.Gnatchop_File.all = "" then
873
         return Get_File (File, With_Dir);
874
      else
875
         return File.Gnatchop_File.all;
876
      end if;
877
   end Get_Gnatchop_File;
878
 
879
   function Get_Gnatchop_File
880
     (Ref      : Reference;
881
      With_Dir : Boolean := False)
882
      return     String
883
   is
884
   begin
885
      return Get_Gnatchop_File (Ref.File, With_Dir);
886
   end Get_Gnatchop_File;
887
 
888
   function Get_Gnatchop_File
889
     (Decl     : Declaration_Reference;
890
      With_Dir : Boolean := False)
891
      return     String
892
   is
893
   begin
894
      return Get_Gnatchop_File (Decl.Decl.File, With_Dir);
895
   end Get_Gnatchop_File;
896
 
897
   --------------
898
   -- Get_Line --
899
   --------------
900
 
901
   function Get_Line (Decl : Declaration_Reference) return String is
902
   begin
903
      return Ada.Strings.Fixed.Trim (Natural'Image (Decl.Decl.Line),
904
                                     Ada.Strings.Left);
905
   end Get_Line;
906
 
907
   function Get_Line (Ref : Reference) return String is
908
   begin
909
      return Ada.Strings.Fixed.Trim (Natural'Image (Ref.Line),
910
                                     Ada.Strings.Left);
911
   end Get_Line;
912
 
913
   ----------------
914
   -- Get_Parent --
915
   ----------------
916
 
917
   function Get_Parent
918
     (Decl : Declaration_Reference)
919
      return Declaration_Reference
920
   is
921
   begin
922
      return Decl.Par_Symbol;
923
   end Get_Parent;
924
 
925
   ---------------------
926
   -- Get_Source_Line --
927
   ---------------------
928
 
929
   function Get_Source_Line (Ref : Reference) return String is
930
   begin
931
      if Ref.Source_Line /= null then
932
         return Ref.Source_Line.all;
933
      else
934
         return "";
935
      end if;
936
   end Get_Source_Line;
937
 
938
   function Get_Source_Line (Decl : Declaration_Reference) return String is
939
   begin
940
      if Decl.Decl.Source_Line /= null then
941
         return Decl.Decl.Source_Line.all;
942
      else
943
         return "";
944
      end if;
945
   end Get_Source_Line;
946
 
947
   ----------------
948
   -- Get_Symbol --
949
   ----------------
950
 
951
   function Get_Symbol (Decl : Declaration_Reference) return String is
952
   begin
953
      return Decl.Symbol;
954
   end Get_Symbol;
955
 
956
   --------------
957
   -- Get_Type --
958
   --------------
959
 
960
   function Get_Type (Decl : Declaration_Reference) return Character is
961
   begin
962
      return Decl.Decl_Type;
963
   end Get_Type;
964
 
965
   ----------
966
   -- Sort --
967
   ----------
968
 
969
   procedure Sort (Arr : in out Reference_Array) is
970
      Tmp : Reference;
971
 
972
      function Lt (Op1, Op2 : Natural) return Boolean;
973
      procedure Move (From, To : Natural);
974
      --  See GNAT.Heap_Sort_G
975
 
976
      --------
977
      -- Lt --
978
      --------
979
 
980
      function Lt (Op1, Op2 : Natural) return Boolean is
981
      begin
982
         if Op1 = 0 then
983
            return Is_Less_Than (Tmp, Arr (Op2));
984
         elsif Op2 = 0 then
985
            return Is_Less_Than (Arr (Op1), Tmp);
986
         else
987
            return Is_Less_Than (Arr (Op1), Arr (Op2));
988
         end if;
989
      end Lt;
990
 
991
      ----------
992
      -- Move --
993
      ----------
994
 
995
      procedure Move (From, To : Natural) is
996
      begin
997
         if To = 0 then
998
            Tmp := Arr (From);
999
         elsif From = 0 then
1000
            Arr (To) := Tmp;
1001
         else
1002
            Arr (To) := Arr (From);
1003
         end if;
1004
      end Move;
1005
 
1006
      package Ref_Sort is new GNAT.Heap_Sort_G (Move, Lt);
1007
 
1008
   --  Start of processing for Sort
1009
 
1010
   begin
1011
      Ref_Sort.Sort (Arr'Last);
1012
   end Sort;
1013
 
1014
   -----------------------
1015
   -- Grep_Source_Files --
1016
   -----------------------
1017
 
1018
   procedure Grep_Source_Files is
1019
      Length       : Natural := 0;
1020
      Decl         : Declaration_Reference := Entities_HTable.Get_First;
1021
      Arr          : Reference_Array_Access;
1022
      Index        : Natural;
1023
      End_Index    : Natural;
1024
      Current_File : File_Reference;
1025
      Current_Line : Cst_String_Access;
1026
      Buffer       : GNAT.OS_Lib.String_Access;
1027
      Ref          : Reference;
1028
      Line         : Natural;
1029
 
1030
   begin
1031
      --  Create a temporary array, where all references will be
1032
      --  sorted by files. This way, we only have to read the source
1033
      --  files once.
1034
 
1035
      while Decl /= null loop
1036
 
1037
         --  Add 1 for the declaration itself
1038
 
1039
         Length := Length + References_Count (Decl, True, True, True) + 1;
1040
         Decl := Entities_HTable.Get_Next;
1041
      end loop;
1042
 
1043
      Arr := new Reference_Array (1 .. Length);
1044
      Index := Arr'First;
1045
 
1046
      Decl := Entities_HTable.Get_First;
1047
      while Decl /= null loop
1048
         Store_References (Decl, True, True, True, True, Arr.all, Index);
1049
         Decl := Entities_HTable.Get_Next;
1050
      end loop;
1051
 
1052
      Sort (Arr.all);
1053
 
1054
      --  Now traverse the whole array and find the appropriate source
1055
      --  lines.
1056
 
1057
      for R in Arr'Range loop
1058
         Ref := Arr (R);
1059
 
1060
         if Ref.File /= Current_File then
1061
            Free (Buffer);
1062
            begin
1063
               Read_File (Get_File (Ref.File, With_Dir => True), Buffer);
1064
               End_Index := Buffer'First - 1;
1065
               Line := 0;
1066
            exception
1067
               when Ada.Text_IO.Name_Error | Ada.Text_IO.End_Error =>
1068
                  Line := Natural'Last;
1069
            end;
1070
            Current_File := Ref.File;
1071
         end if;
1072
 
1073
         if Ref.Line > Line then
1074
 
1075
            --  Do not free Current_Line, it is referenced by the last
1076
            --  Ref we processed.
1077
 
1078
            loop
1079
               Index := End_Index + 1;
1080
 
1081
               loop
1082
                  End_Index := End_Index + 1;
1083
                  exit when End_Index > Buffer'Last
1084
                    or else Buffer (End_Index) = ASCII.LF;
1085
               end loop;
1086
 
1087
               --  Skip spaces at beginning of line
1088
 
1089
               while Index < End_Index and then
1090
                 (Buffer (Index) = ' ' or else Buffer (Index) = ASCII.HT)
1091
               loop
1092
                  Index := Index + 1;
1093
               end loop;
1094
 
1095
               Line := Line + 1;
1096
               exit when Ref.Line = Line;
1097
            end loop;
1098
 
1099
            Current_Line := new String'(Buffer (Index .. End_Index - 1));
1100
         end if;
1101
 
1102
         Ref.Source_Line := Current_Line;
1103
      end loop;
1104
 
1105
      Free (Buffer);
1106
      Free (Arr);
1107
   end Grep_Source_Files;
1108
 
1109
   ---------------
1110
   -- Read_File --
1111
   ---------------
1112
 
1113
   procedure Read_File
1114
     (File_Name : String;
1115
      Contents  : out GNAT.OS_Lib.String_Access)
1116
   is
1117
      Name_0 : constant String := File_Name & ASCII.NUL;
1118
      FD     : constant File_Descriptor := Open_Read (Name_0'Address, Binary);
1119
      Length : Natural;
1120
 
1121
   begin
1122
      if FD = Invalid_FD then
1123
         raise Ada.Text_IO.Name_Error;
1124
      end if;
1125
 
1126
      --  Include room for EOF char
1127
 
1128
      Length := Natural (File_Length (FD));
1129
 
1130
      declare
1131
         Buffer    : String (1 .. Length + 1);
1132
         This_Read : Integer;
1133
         Read_Ptr  : Natural := 1;
1134
 
1135
      begin
1136
         loop
1137
            This_Read := Read (FD,
1138
                               A => Buffer (Read_Ptr)'Address,
1139
                               N => Length + 1 - Read_Ptr);
1140
            Read_Ptr := Read_Ptr + Integer'Max (This_Read, 0);
1141
            exit when This_Read <= 0;
1142
         end loop;
1143
 
1144
         Buffer (Read_Ptr) := EOF;
1145
         Contents := new String'(Buffer (1 .. Read_Ptr));
1146
 
1147
         --  Things are not simple on VMS due to the plethora of file types
1148
         --  and organizations. It seems clear that there shouldn't be more
1149
         --  bytes read than are contained in the file though.
1150
 
1151
         if (Hostparm.OpenVMS and then Read_Ptr > Length + 1)
1152
           or else (not Hostparm.OpenVMS and then Read_Ptr /= Length + 1)
1153
         then
1154
            raise Ada.Text_IO.End_Error;
1155
         end if;
1156
 
1157
         Close (FD);
1158
      end;
1159
   end Read_File;
1160
 
1161
   -----------------------
1162
   -- Longest_File_Name --
1163
   -----------------------
1164
 
1165
   function Longest_File_Name return Natural is
1166
   begin
1167
      return Longest_File_Name_In_Table;
1168
   end Longest_File_Name;
1169
 
1170
   -----------
1171
   -- Match --
1172
   -----------
1173
 
1174
   function Match
1175
     (File   : File_Reference;
1176
      Line   : Natural;
1177
      Column : Natural)
1178
      return   Boolean
1179
   is
1180
      Ref : Ref_In_File_Ptr := File.Lines;
1181
 
1182
   begin
1183
      while Ref /= null loop
1184
         if (Ref.Line = 0 or else Ref.Line = Line)
1185
           and then (Ref.Column = 0 or else Ref.Column = Column)
1186
         then
1187
            return True;
1188
         end if;
1189
 
1190
         Ref := Ref.Next;
1191
      end loop;
1192
 
1193
      return False;
1194
   end Match;
1195
 
1196
   -----------
1197
   -- Match --
1198
   -----------
1199
 
1200
   function Match (Decl : Declaration_Reference) return Boolean is
1201
   begin
1202
      return Decl.Match;
1203
   end Match;
1204
 
1205
   ----------
1206
   -- Next --
1207
   ----------
1208
 
1209
   function Next (E : File_Reference) return File_Reference is
1210
   begin
1211
      return E.Next;
1212
   end Next;
1213
 
1214
   function Next (E : Declaration_Reference) return Declaration_Reference is
1215
   begin
1216
      return E.Next;
1217
   end Next;
1218
 
1219
   ------------------
1220
   -- Next_Obj_Dir --
1221
   ------------------
1222
 
1223
   function Next_Obj_Dir return String is
1224
      First : constant Integer := Directories.Obj_Dir_Index;
1225
      Last  : Integer;
1226
 
1227
   begin
1228
      Last := Directories.Obj_Dir_Index;
1229
 
1230
      if Last > Directories.Obj_Dir_Length then
1231
         return String'(1 .. 0 => ' ');
1232
      end if;
1233
 
1234
      while Directories.Obj_Dir (Last) /= Path_Separator loop
1235
         Last := Last + 1;
1236
      end loop;
1237
 
1238
      Directories.Obj_Dir_Index := Last + 1;
1239
      Directories.Last_Obj_Dir_Start := First;
1240
      return Directories.Obj_Dir (First .. Last - 1);
1241
   end Next_Obj_Dir;
1242
 
1243
   -------------------------
1244
   -- Next_Unvisited_File --
1245
   -------------------------
1246
 
1247
   function Next_Unvisited_File return File_Reference is
1248
      procedure Unchecked_Free is new Ada.Unchecked_Deallocation
1249
        (Unvisited_Files_Record, Unvisited_Files_Access);
1250
 
1251
      Ref : File_Reference;
1252
      Tmp : Unvisited_Files_Access;
1253
 
1254
   begin
1255
      if Unvisited_Files = null then
1256
         return Empty_File;
1257
      else
1258
         Tmp := Unvisited_Files;
1259
         Ref := Unvisited_Files.File;
1260
         Unvisited_Files := Unvisited_Files.Next;
1261
         Unchecked_Free (Tmp);
1262
         return Ref;
1263
      end if;
1264
   end Next_Unvisited_File;
1265
 
1266
   ----------------------
1267
   -- Parse_Gnatls_Src --
1268
   ----------------------
1269
 
1270
   function Parse_Gnatls_Src return String is
1271
      Length : Natural;
1272
 
1273
   begin
1274
      Length := 0;
1275
      for J in 1 .. Osint.Nb_Dir_In_Src_Search_Path loop
1276
         if Osint.Dir_In_Src_Search_Path (J)'Length = 0 then
1277
            Length := Length + 2;
1278
         else
1279
            Length := Length + Osint.Dir_In_Src_Search_Path (J)'Length + 1;
1280
         end if;
1281
      end loop;
1282
 
1283
      declare
1284
         Result : String (1 .. Length);
1285
         L      : Natural;
1286
 
1287
      begin
1288
         L := Result'First;
1289
         for J in 1 .. Osint.Nb_Dir_In_Src_Search_Path loop
1290
            if Osint.Dir_In_Src_Search_Path (J)'Length = 0 then
1291
               Result (L .. L + 1) := "." & Path_Separator;
1292
               L := L + 2;
1293
 
1294
            else
1295
               Result (L .. L + Osint.Dir_In_Src_Search_Path (J)'Length - 1) :=
1296
                 Osint.Dir_In_Src_Search_Path (J).all;
1297
               L := L + Osint.Dir_In_Src_Search_Path (J)'Length;
1298
               Result (L) := Path_Separator;
1299
               L := L + 1;
1300
            end if;
1301
         end loop;
1302
 
1303
         return Result;
1304
      end;
1305
   end Parse_Gnatls_Src;
1306
 
1307
   ----------------------
1308
   -- Parse_Gnatls_Obj --
1309
   ----------------------
1310
 
1311
   function Parse_Gnatls_Obj return String is
1312
      Length : Natural;
1313
 
1314
   begin
1315
      Length := 0;
1316
      for J in 1 .. Osint.Nb_Dir_In_Obj_Search_Path loop
1317
         if Osint.Dir_In_Obj_Search_Path (J)'Length = 0 then
1318
            Length := Length + 2;
1319
         else
1320
            Length := Length + Osint.Dir_In_Obj_Search_Path (J)'Length + 1;
1321
         end if;
1322
      end loop;
1323
 
1324
      declare
1325
         Result : String (1 .. Length);
1326
         L      : Natural;
1327
 
1328
      begin
1329
         L := Result'First;
1330
         for J in 1 .. Osint.Nb_Dir_In_Obj_Search_Path loop
1331
            if Osint.Dir_In_Obj_Search_Path (J)'Length = 0 then
1332
               Result (L .. L + 1) := "." & Path_Separator;
1333
               L := L + 2;
1334
            else
1335
               Result (L .. L + Osint.Dir_In_Obj_Search_Path (J)'Length - 1) :=
1336
                 Osint.Dir_In_Obj_Search_Path (J).all;
1337
               L := L + Osint.Dir_In_Obj_Search_Path (J)'Length;
1338
               Result (L) := Path_Separator;
1339
               L := L + 1;
1340
            end if;
1341
         end loop;
1342
 
1343
         return Result;
1344
      end;
1345
   end Parse_Gnatls_Obj;
1346
 
1347
   -------------------
1348
   -- Reset_Obj_Dir --
1349
   -------------------
1350
 
1351
   procedure Reset_Obj_Dir is
1352
   begin
1353
      Directories.Obj_Dir_Index := 1;
1354
   end Reset_Obj_Dir;
1355
 
1356
   -----------------------
1357
   -- Set_Default_Match --
1358
   -----------------------
1359
 
1360
   procedure Set_Default_Match (Value : Boolean) is
1361
   begin
1362
      Default_Match := Value;
1363
   end Set_Default_Match;
1364
 
1365
   ----------
1366
   -- Free --
1367
   ----------
1368
 
1369
   procedure Free (Str : in out Cst_String_Access) is
1370
      function Convert is new Ada.Unchecked_Conversion
1371
        (Cst_String_Access, GNAT.OS_Lib.String_Access);
1372
 
1373
      S : GNAT.OS_Lib.String_Access := Convert (Str);
1374
 
1375
   begin
1376
      Free (S);
1377
      Str := null;
1378
   end Free;
1379
 
1380
   ---------------------
1381
   -- Reset_Directory --
1382
   ---------------------
1383
 
1384
   procedure Reset_Directory (File : File_Reference) is
1385
   begin
1386
      Free (File.Dir);
1387
   end Reset_Directory;
1388
 
1389
   -------------------
1390
   -- Set_Unvisited --
1391
   -------------------
1392
 
1393
   procedure Set_Unvisited (File_Ref : File_Reference) is
1394
      F : constant String := Get_File (File_Ref, With_Dir => False);
1395
 
1396
   begin
1397
      File_Ref.Visited := False;
1398
 
1399
      --  ??? Do not add a source file to the list. This is true at
1400
      --  least for gnatxref, and probably for gnatfind as well
1401
 
1402
      if F'Length > 4
1403
        and then F (F'Last - 3 .. F'Last) = "." & Osint.ALI_Suffix.all
1404
      then
1405
         Unvisited_Files := new Unvisited_Files_Record'
1406
           (File => File_Ref,
1407
            Next => Unvisited_Files);
1408
      end if;
1409
   end Set_Unvisited;
1410
 
1411
   ----------------------
1412
   -- Get_Declarations --
1413
   ----------------------
1414
 
1415
   function Get_Declarations
1416
     (Sorted : Boolean := True)
1417
      return   Declaration_Array_Access
1418
   is
1419
      Arr   : constant Declaration_Array_Access :=
1420
                new Declaration_Array (1 .. Entities_Count);
1421
      Decl  : Declaration_Reference := Entities_HTable.Get_First;
1422
      Index : Natural               := Arr'First;
1423
      Tmp   : Declaration_Reference;
1424
 
1425
      procedure Move (From : Natural; To : Natural);
1426
      function Lt (Op1, Op2 : Natural) return Boolean;
1427
      --  See GNAT.Heap_Sort_G
1428
 
1429
      --------
1430
      -- Lt --
1431
      --------
1432
 
1433
      function Lt (Op1, Op2 : Natural) return Boolean is
1434
      begin
1435
         if Op1 = 0 then
1436
            return Is_Less_Than (Tmp, Arr (Op2));
1437
         elsif Op2 = 0 then
1438
            return Is_Less_Than (Arr (Op1), Tmp);
1439
         else
1440
            return Is_Less_Than (Arr (Op1), Arr (Op2));
1441
         end if;
1442
      end Lt;
1443
 
1444
      ----------
1445
      -- Move --
1446
      ----------
1447
 
1448
      procedure Move (From : Natural; To : Natural) is
1449
      begin
1450
         if To = 0 then
1451
            Tmp := Arr (From);
1452
         elsif From = 0 then
1453
            Arr (To) := Tmp;
1454
         else
1455
            Arr (To) := Arr (From);
1456
         end if;
1457
      end Move;
1458
 
1459
      package Decl_Sort is new GNAT.Heap_Sort_G (Move, Lt);
1460
 
1461
   --  Start of processing for Get_Declarations
1462
 
1463
   begin
1464
      while Decl /= null loop
1465
         Arr (Index) := Decl;
1466
         Index := Index + 1;
1467
         Decl := Entities_HTable.Get_Next;
1468
      end loop;
1469
 
1470
      if Sorted and then Arr'Length /= 0 then
1471
         Decl_Sort.Sort (Entities_Count);
1472
      end if;
1473
 
1474
      return Arr;
1475
   end Get_Declarations;
1476
 
1477
   ----------------------
1478
   -- References_Count --
1479
   ----------------------
1480
 
1481
   function References_Count
1482
     (Decl       : Declaration_Reference;
1483
      Get_Reads  : Boolean := False;
1484
      Get_Writes : Boolean := False;
1485
      Get_Bodies : Boolean := False)
1486
      return       Natural
1487
   is
1488
      function List_Length (E : Reference) return Natural;
1489
      --  Return the number of references in E
1490
 
1491
      -----------------
1492
      -- List_Length --
1493
      -----------------
1494
 
1495
      function List_Length (E : Reference) return Natural is
1496
         L  : Natural := 0;
1497
         E1 : Reference := E;
1498
 
1499
      begin
1500
         while E1 /= null loop
1501
            L := L + 1;
1502
            E1 := E1.Next;
1503
         end loop;
1504
 
1505
         return L;
1506
      end List_Length;
1507
 
1508
      Length : Natural := 0;
1509
 
1510
   --  Start of processing for References_Count
1511
 
1512
   begin
1513
      if Get_Reads then
1514
         Length := List_Length (Decl.Ref_Ref);
1515
      end if;
1516
 
1517
      if Get_Writes then
1518
         Length := Length + List_Length (Decl.Modif_Ref);
1519
      end if;
1520
 
1521
      if Get_Bodies then
1522
         Length := Length + List_Length (Decl.Body_Ref);
1523
      end if;
1524
 
1525
      return Length;
1526
   end References_Count;
1527
 
1528
   ----------------------
1529
   -- Store_References --
1530
   ----------------------
1531
 
1532
   procedure Store_References
1533
     (Decl            : Declaration_Reference;
1534
      Get_Writes      : Boolean := False;
1535
      Get_Reads       : Boolean := False;
1536
      Get_Bodies      : Boolean := False;
1537
      Get_Declaration : Boolean := False;
1538
      Arr             : in out Reference_Array;
1539
      Index           : in out Natural)
1540
   is
1541
      procedure Add (List : Reference);
1542
      --  Add all the references in List to Arr
1543
 
1544
      ---------
1545
      -- Add --
1546
      ---------
1547
 
1548
      procedure Add (List : Reference) is
1549
         E : Reference := List;
1550
      begin
1551
         while E /= null loop
1552
            Arr (Index) := E;
1553
            Index := Index + 1;
1554
            E := E.Next;
1555
         end loop;
1556
      end Add;
1557
 
1558
   --  Start of processing for Store_References
1559
 
1560
   begin
1561
      if Get_Declaration then
1562
         Add (Decl.Decl);
1563
      end if;
1564
 
1565
      if Get_Reads then
1566
         Add (Decl.Ref_Ref);
1567
      end if;
1568
 
1569
      if Get_Writes then
1570
         Add (Decl.Modif_Ref);
1571
      end if;
1572
 
1573
      if Get_Bodies then
1574
         Add (Decl.Body_Ref);
1575
      end if;
1576
   end Store_References;
1577
 
1578
   --------------------
1579
   -- Get_References --
1580
   --------------------
1581
 
1582
   function Get_References
1583
     (Decl : Declaration_Reference;
1584
      Get_Reads  : Boolean := False;
1585
      Get_Writes : Boolean := False;
1586
      Get_Bodies : Boolean := False)
1587
      return       Reference_Array_Access
1588
   is
1589
      Length : constant Natural :=
1590
                 References_Count (Decl, Get_Reads, Get_Writes, Get_Bodies);
1591
 
1592
      Arr : constant Reference_Array_Access :=
1593
              new Reference_Array (1 .. Length);
1594
 
1595
      Index : Natural := Arr'First;
1596
 
1597
   begin
1598
      Store_References
1599
        (Decl            => Decl,
1600
         Get_Writes      => Get_Writes,
1601
         Get_Reads       => Get_Reads,
1602
         Get_Bodies      => Get_Bodies,
1603
         Get_Declaration => False,
1604
         Arr             => Arr.all,
1605
         Index           => Index);
1606
 
1607
      if Arr'Length /= 0 then
1608
         Sort (Arr.all);
1609
      end if;
1610
 
1611
      return Arr;
1612
   end Get_References;
1613
 
1614
   ----------
1615
   -- Free --
1616
   ----------
1617
 
1618
   procedure Free (Arr : in out Reference_Array_Access) is
1619
      procedure Internal is new Ada.Unchecked_Deallocation
1620
        (Reference_Array, Reference_Array_Access);
1621
   begin
1622
      Internal (Arr);
1623
   end Free;
1624
 
1625
   ------------------
1626
   -- Is_Parameter --
1627
   ------------------
1628
 
1629
   function Is_Parameter (Decl : Declaration_Reference) return Boolean is
1630
   begin
1631
      return Decl.Is_Parameter;
1632
   end Is_Parameter;
1633
 
1634
end Xr_Tabls;

powered by: WebSVN 2.1.0

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