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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [xr_tabls.adb] - Blame information for rev 307

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

Line No. Rev Author Line
1 281 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-2009, 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' | 'm' | 'r' | 'R' | 'i' | ' ' | 'x' =>
399
            null;
400
 
401
         when 'l' | 'w' =>
402
            if not Labels_As_Ref then
403
               return;
404
            end if;
405
 
406
         when '=' | '<' | '>' | '^' =>
407
 
408
            --  Create a dummy declaration in the table to report it as a
409
            --  parameter. Note that the current declaration for the subprogram
410
            --  comes before the declaration of the parameter.
411
 
412
            declare
413
               Key      : constant String :=
414
                            Key_From_Ref (File_Ref, Line, Column);
415
               New_Decl : Declaration_Reference;
416
 
417
            begin
418
               New_Decl := new Declaration_Record'
419
                 (Symbol_Length => 0,
420
                  Symbol        => "",
421
                  Key           => new String'(Key),
422
                  Decl          => null,
423
                  Is_Parameter  => True,
424
                  Decl_Type     => ' ',
425
                  Body_Ref      => null,
426
                  Ref_Ref       => null,
427
                  Modif_Ref     => null,
428
                  Match         => False,
429
                  Par_Symbol    => null,
430
                  Next          => null);
431
               Entities_HTable.Set (New_Decl);
432
               Entities_Count := Entities_Count + 1;
433
            end;
434
 
435
         when 'e' | 'z' | 't' | 'p' | 'P' | 'k' | 'd' =>
436
            return;
437
 
438
         when others    =>
439
            Ada.Text_IO.Put_Line ("Unknown reference type: " & Ref_Type);
440
            return;
441
      end case;
442
 
443
      New_Ref := new Reference_Record'
444
        (File        => File_Ref,
445
         Line        => Line,
446
         Column      => Column,
447
         Source_Line => null,
448
         Next        => null);
449
 
450
      --  We can insert the reference in the list directly, since all
451
      --  the references will appear only once in the ALI file
452
      --  corresponding to the file where they are referenced.
453
      --  This saves a lot of time compared to checking the list to check
454
      --  if it exists.
455
 
456
      case Ref_Type is
457
         when 'b' | 'c' =>
458
            New_Ref.Next          := Declaration.Body_Ref;
459
            Declaration.Body_Ref  := New_Ref;
460
 
461
         when 'r' | 'R' | 'i' | 'l' | ' ' | 'x' | 'w' =>
462
            New_Ref.Next          := Declaration.Ref_Ref;
463
            Declaration.Ref_Ref   := New_Ref;
464
 
465
         when 'm' =>
466
            New_Ref.Next          := Declaration.Modif_Ref;
467
            Declaration.Modif_Ref := New_Ref;
468
 
469
         when others =>
470
            null;
471
      end case;
472
 
473
      if not Declaration.Match then
474
         Declaration.Match := Match (File_Ref, Line, Column);
475
      end if;
476
 
477
      if Declaration.Match then
478
         Longest_File_Name_In_Table :=
479
           Natural'Max (File_Ref.File'Length, Longest_File_Name_In_Table);
480
      end if;
481
   end Add_Reference;
482
 
483
   -------------------
484
   -- ALI_File_Name --
485
   -------------------
486
 
487
   function ALI_File_Name (Ada_File_Name : String) return String is
488
 
489
      --  ??? Should ideally be based on the naming scheme defined in
490
      --  project files.
491
 
492
      Index : constant Natural :=
493
                Ada.Strings.Fixed.Index
494
                  (Ada_File_Name, ".", Going => Ada.Strings.Backward);
495
 
496
   begin
497
      if Index /= 0 then
498
         return Ada_File_Name (Ada_File_Name'First .. Index)
499
           & Osint.ALI_Suffix.all;
500
      else
501
         return Ada_File_Name & "." & Osint.ALI_Suffix.all;
502
      end if;
503
   end ALI_File_Name;
504
 
505
   ------------------
506
   -- Is_Less_Than --
507
   ------------------
508
 
509
   function Is_Less_Than (Ref1, Ref2 : Reference) return Boolean is
510
   begin
511
      if Ref1 = null then
512
         return False;
513
      elsif Ref2 = null then
514
         return True;
515
      end if;
516
 
517
      if Ref1.File.File.all < Ref2.File.File.all then
518
         return True;
519
 
520
      elsif Ref1.File.File.all = Ref2.File.File.all then
521
         return (Ref1.Line < Ref2.Line
522
                 or else (Ref1.Line = Ref2.Line
523
                          and then Ref1.Column < Ref2.Column));
524
      end if;
525
 
526
      return False;
527
   end Is_Less_Than;
528
 
529
   ------------------
530
   -- Is_Less_Than --
531
   ------------------
532
 
533
   function Is_Less_Than (Decl1, Decl2 : Declaration_Reference) return Boolean
534
   is
535
      --  We cannot store the data case-insensitive in the table,
536
      --  since we wouldn't be able to find the right casing for the
537
      --  display later on.
538
 
539
      S1 : constant String := To_Lower (Decl1.Symbol);
540
      S2 : constant String := To_Lower (Decl2.Symbol);
541
 
542
   begin
543
      if S1 < S2 then
544
         return True;
545
      elsif S1 > S2 then
546
         return False;
547
      end if;
548
 
549
      return Decl1.Key.all < Decl2.Key.all;
550
   end Is_Less_Than;
551
 
552
   -------------------------
553
   -- Create_Project_File --
554
   -------------------------
555
 
556
   procedure Create_Project_File (Name : String) is
557
      Obj_Dir     : Unbounded_String := Null_Unbounded_String;
558
      Src_Dir     : Unbounded_String := Null_Unbounded_String;
559
      Build_Dir   : GNAT.OS_Lib.String_Access := new String'("");
560
 
561
      F           : File_Descriptor;
562
      Len         : Positive;
563
      File_Name   : aliased String := Name & ASCII.NUL;
564
 
565
   begin
566
      --  Read the size of the file
567
 
568
      F := Open_Read (File_Name'Address, Text);
569
 
570
      --  Project file not found
571
 
572
      if F /= Invalid_FD then
573
         Len := Positive (File_Length (F));
574
 
575
         declare
576
            Buffer : String (1 .. Len);
577
            Index  : Positive := Buffer'First;
578
            Last   : Positive;
579
 
580
         begin
581
            Len := Read (F, Buffer'Address, Len);
582
            Close (F);
583
 
584
            --  First, look for Build_Dir, since all the source and object
585
            --  path are relative to it.
586
 
587
            while Index <= Buffer'Last loop
588
 
589
               --  Find the end of line
590
 
591
               Last := Index;
592
               while Last <= Buffer'Last
593
                 and then Buffer (Last) /= ASCII.LF
594
                 and then Buffer (Last) /= ASCII.CR
595
               loop
596
                  Last := Last + 1;
597
               end loop;
598
 
599
               if Index <= Buffer'Last - 9
600
                 and then Buffer (Index .. Index + 9) = "build_dir="
601
               then
602
                  Index := Index + 10;
603
                  while Index <= Last
604
                    and then (Buffer (Index) = ' '
605
                              or else Buffer (Index) = ASCII.HT)
606
                  loop
607
                     Index := Index + 1;
608
                  end loop;
609
 
610
                  Free (Build_Dir);
611
                  Build_Dir := new String'(Buffer (Index .. Last - 1));
612
               end if;
613
 
614
               Index := Last + 1;
615
 
616
               --  In case we had a ASCII.CR/ASCII.LF end of line, skip the
617
               --  remaining symbol
618
 
619
               if Index <= Buffer'Last
620
                 and then Buffer (Index) = ASCII.LF
621
               then
622
                  Index := Index + 1;
623
               end if;
624
            end loop;
625
 
626
            --  Now parse the source and object paths
627
 
628
            Index := Buffer'First;
629
            while Index <= Buffer'Last loop
630
 
631
               --  Find the end of line
632
 
633
               Last := Index;
634
               while Last <= Buffer'Last
635
                 and then Buffer (Last) /= ASCII.LF
636
                 and then Buffer (Last) /= ASCII.CR
637
               loop
638
                  Last := Last + 1;
639
               end loop;
640
 
641
               if Index <= Buffer'Last - 7
642
                 and then Buffer (Index .. Index + 7) = "src_dir="
643
               then
644
                  Append (Src_Dir, Normalize_Pathname
645
                          (Name      => Ada.Strings.Fixed.Trim
646
                           (Buffer (Index + 8 .. Last - 1), Ada.Strings.Both),
647
                           Directory => Build_Dir.all) & Path_Separator);
648
 
649
               elsif Index <= Buffer'Last - 7
650
                 and then Buffer (Index .. Index + 7) = "obj_dir="
651
               then
652
                  Append (Obj_Dir, Normalize_Pathname
653
                          (Name      => Ada.Strings.Fixed.Trim
654
                           (Buffer (Index + 8 .. Last - 1), Ada.Strings.Both),
655
                           Directory => Build_Dir.all) & Path_Separator);
656
               end if;
657
 
658
               --  In case we had a ASCII.CR/ASCII.LF end of line, skip the
659
               --  remaining symbol
660
               Index := Last + 1;
661
 
662
               if Index <= Buffer'Last
663
                 and then Buffer (Index) = ASCII.LF
664
               then
665
                  Index := Index + 1;
666
               end if;
667
            end loop;
668
         end;
669
      end if;
670
 
671
      Osint.Add_Default_Search_Dirs;
672
 
673
      declare
674
         Src : constant String := Parse_Gnatls_Src;
675
         Obj : constant String := Parse_Gnatls_Obj;
676
 
677
      begin
678
         Directories := new Project_File'
679
           (Src_Dir_Length     => Length (Src_Dir) + Src'Length,
680
            Obj_Dir_Length     => Length (Obj_Dir) + Obj'Length,
681
            Src_Dir            => To_String (Src_Dir) & Src,
682
            Obj_Dir            => To_String (Obj_Dir) & Obj,
683
            Src_Dir_Index      => 1,
684
            Obj_Dir_Index      => 1,
685
            Last_Obj_Dir_Start => 0);
686
      end;
687
 
688
      Free (Build_Dir);
689
   end Create_Project_File;
690
 
691
   ---------------------
692
   -- Current_Obj_Dir --
693
   ---------------------
694
 
695
   function Current_Obj_Dir return String is
696
   begin
697
      return Directories.Obj_Dir
698
        (Directories.Last_Obj_Dir_Start .. Directories.Obj_Dir_Index - 2);
699
   end Current_Obj_Dir;
700
 
701
   ----------------
702
   -- Get_Column --
703
   ----------------
704
 
705
   function Get_Column (Decl : Declaration_Reference) return String is
706
   begin
707
      return Ada.Strings.Fixed.Trim (Natural'Image (Decl.Decl.Column),
708
                                     Ada.Strings.Left);
709
   end Get_Column;
710
 
711
   function Get_Column (Ref : Reference) return String is
712
   begin
713
      return Ada.Strings.Fixed.Trim (Natural'Image (Ref.Column),
714
                                     Ada.Strings.Left);
715
   end Get_Column;
716
 
717
   ---------------------
718
   -- Get_Declaration --
719
   ---------------------
720
 
721
   function Get_Declaration
722
     (File_Ref : File_Reference;
723
      Line     : Natural;
724
      Column   : Natural)
725
      return     Declaration_Reference
726
   is
727
      Key : aliased constant String := Key_From_Ref (File_Ref, Line, Column);
728
 
729
   begin
730
      return Entities_HTable.Get (Key'Unchecked_Access);
731
   end Get_Declaration;
732
 
733
   ----------------------
734
   -- Get_Emit_Warning --
735
   ----------------------
736
 
737
   function Get_Emit_Warning (File : File_Reference) return Boolean is
738
   begin
739
      return File.Emit_Warning;
740
   end Get_Emit_Warning;
741
 
742
   --------------
743
   -- Get_File --
744
   --------------
745
 
746
   function Get_File
747
     (Decl     : Declaration_Reference;
748
      With_Dir : Boolean := False) return String
749
   is
750
   begin
751
      return Get_File (Decl.Decl.File, With_Dir);
752
   end Get_File;
753
 
754
   function Get_File
755
     (Ref      : Reference;
756
      With_Dir : Boolean := False) return String
757
   is
758
   begin
759
      return Get_File (Ref.File, With_Dir);
760
   end Get_File;
761
 
762
   function Get_File
763
     (File     : File_Reference;
764
      With_Dir : Boolean := False;
765
      Strip    : Natural    := 0) return String
766
   is
767
      Tmp : GNAT.OS_Lib.String_Access;
768
 
769
      function Internal_Strip (Full_Name : String) return String;
770
      --  Internal function to process the Strip parameter
771
 
772
      --------------------
773
      -- Internal_Strip --
774
      --------------------
775
 
776
      function Internal_Strip (Full_Name : String) return String is
777
         Unit_End        : Natural;
778
         Extension_Start : Natural;
779
         S               : Natural;
780
 
781
      begin
782
         if Strip = 0 then
783
            return Full_Name;
784
         end if;
785
 
786
         --  Isolate the file extension
787
 
788
         Extension_Start := Full_Name'Last;
789
         while Extension_Start >= Full_Name'First
790
           and then Full_Name (Extension_Start) /= '.'
791
         loop
792
            Extension_Start := Extension_Start - 1;
793
         end loop;
794
 
795
         --  Strip the right number of subunit_names
796
 
797
         S := Strip;
798
         Unit_End := Extension_Start - 1;
799
         while Unit_End >= Full_Name'First
800
           and then S > 0
801
         loop
802
            if Full_Name (Unit_End) = '-' then
803
               S := S - 1;
804
            end if;
805
 
806
            Unit_End := Unit_End - 1;
807
         end loop;
808
 
809
         if Unit_End < Full_Name'First then
810
            return "";
811
         else
812
            return Full_Name (Full_Name'First .. Unit_End)
813
              & Full_Name (Extension_Start .. Full_Name'Last);
814
         end if;
815
      end Internal_Strip;
816
 
817
   --  Start of processing for Get_File;
818
 
819
   begin
820
      --  If we do not want the full path name
821
 
822
      if not With_Dir then
823
         return Internal_Strip (File.File.all);
824
      end if;
825
 
826
      if File.Dir = null then
827
         if Ada.Strings.Fixed.Tail (File.File.all, 3) =
828
                                               Osint.ALI_Suffix.all
829
         then
830
            Tmp := Locate_Regular_File
831
                     (Internal_Strip (File.File.all), Directories.Obj_Dir);
832
         else
833
            Tmp := Locate_Regular_File
834
                     (File.File.all, Directories.Src_Dir);
835
         end if;
836
 
837
         if Tmp = null then
838
            File.Dir := new String'("");
839
         else
840
            File.Dir := new String'(Dir_Name (Tmp.all));
841
            Free (Tmp);
842
         end if;
843
      end if;
844
 
845
      return Internal_Strip (File.Dir.all & File.File.all);
846
   end Get_File;
847
 
848
   ------------------
849
   -- Get_File_Ref --
850
   ------------------
851
 
852
   function Get_File_Ref (Ref : Reference) return File_Reference is
853
   begin
854
      return Ref.File;
855
   end Get_File_Ref;
856
 
857
   -----------------------
858
   -- Get_Gnatchop_File --
859
   -----------------------
860
 
861
   function Get_Gnatchop_File
862
     (File     : File_Reference;
863
      With_Dir : Boolean := False)
864
      return     String
865
   is
866
   begin
867
      if File.Gnatchop_File.all = "" then
868
         return Get_File (File, With_Dir);
869
      else
870
         return File.Gnatchop_File.all;
871
      end if;
872
   end Get_Gnatchop_File;
873
 
874
   function Get_Gnatchop_File
875
     (Ref      : Reference;
876
      With_Dir : Boolean := False)
877
      return     String
878
   is
879
   begin
880
      return Get_Gnatchop_File (Ref.File, With_Dir);
881
   end Get_Gnatchop_File;
882
 
883
   function Get_Gnatchop_File
884
     (Decl     : Declaration_Reference;
885
      With_Dir : Boolean := False)
886
      return     String
887
   is
888
   begin
889
      return Get_Gnatchop_File (Decl.Decl.File, With_Dir);
890
   end Get_Gnatchop_File;
891
 
892
   --------------
893
   -- Get_Line --
894
   --------------
895
 
896
   function Get_Line (Decl : Declaration_Reference) return String is
897
   begin
898
      return Ada.Strings.Fixed.Trim (Natural'Image (Decl.Decl.Line),
899
                                     Ada.Strings.Left);
900
   end Get_Line;
901
 
902
   function Get_Line (Ref : Reference) return String is
903
   begin
904
      return Ada.Strings.Fixed.Trim (Natural'Image (Ref.Line),
905
                                     Ada.Strings.Left);
906
   end Get_Line;
907
 
908
   ----------------
909
   -- Get_Parent --
910
   ----------------
911
 
912
   function Get_Parent
913
     (Decl : Declaration_Reference)
914
      return Declaration_Reference
915
   is
916
   begin
917
      return Decl.Par_Symbol;
918
   end Get_Parent;
919
 
920
   ---------------------
921
   -- Get_Source_Line --
922
   ---------------------
923
 
924
   function Get_Source_Line (Ref : Reference) return String is
925
   begin
926
      if Ref.Source_Line /= null then
927
         return Ref.Source_Line.all;
928
      else
929
         return "";
930
      end if;
931
   end Get_Source_Line;
932
 
933
   function Get_Source_Line (Decl : Declaration_Reference) return String is
934
   begin
935
      if Decl.Decl.Source_Line /= null then
936
         return Decl.Decl.Source_Line.all;
937
      else
938
         return "";
939
      end if;
940
   end Get_Source_Line;
941
 
942
   ----------------
943
   -- Get_Symbol --
944
   ----------------
945
 
946
   function Get_Symbol (Decl : Declaration_Reference) return String is
947
   begin
948
      return Decl.Symbol;
949
   end Get_Symbol;
950
 
951
   --------------
952
   -- Get_Type --
953
   --------------
954
 
955
   function Get_Type (Decl : Declaration_Reference) return Character is
956
   begin
957
      return Decl.Decl_Type;
958
   end Get_Type;
959
 
960
   ----------
961
   -- Sort --
962
   ----------
963
 
964
   procedure Sort (Arr : in out Reference_Array) is
965
      Tmp : Reference;
966
 
967
      function Lt (Op1, Op2 : Natural) return Boolean;
968
      procedure Move (From, To : Natural);
969
      --  See GNAT.Heap_Sort_G
970
 
971
      --------
972
      -- Lt --
973
      --------
974
 
975
      function Lt (Op1, Op2 : Natural) return Boolean is
976
      begin
977
         if Op1 = 0 then
978
            return Is_Less_Than (Tmp, Arr (Op2));
979
         elsif Op2 = 0 then
980
            return Is_Less_Than (Arr (Op1), Tmp);
981
         else
982
            return Is_Less_Than (Arr (Op1), Arr (Op2));
983
         end if;
984
      end Lt;
985
 
986
      ----------
987
      -- Move --
988
      ----------
989
 
990
      procedure Move (From, To : Natural) is
991
      begin
992
         if To = 0 then
993
            Tmp := Arr (From);
994
         elsif From = 0 then
995
            Arr (To) := Tmp;
996
         else
997
            Arr (To) := Arr (From);
998
         end if;
999
      end Move;
1000
 
1001
      package Ref_Sort is new GNAT.Heap_Sort_G (Move, Lt);
1002
 
1003
   --  Start of processing for Sort
1004
 
1005
   begin
1006
      Ref_Sort.Sort (Arr'Last);
1007
   end Sort;
1008
 
1009
   -----------------------
1010
   -- Grep_Source_Files --
1011
   -----------------------
1012
 
1013
   procedure Grep_Source_Files is
1014
      Length       : Natural := 0;
1015
      Decl         : Declaration_Reference := Entities_HTable.Get_First;
1016
      Arr          : Reference_Array_Access;
1017
      Index        : Natural;
1018
      End_Index    : Natural;
1019
      Current_File : File_Reference;
1020
      Current_Line : Cst_String_Access;
1021
      Buffer       : GNAT.OS_Lib.String_Access;
1022
      Ref          : Reference;
1023
      Line         : Natural;
1024
 
1025
   begin
1026
      --  Create a temporary array, where all references will be
1027
      --  sorted by files. This way, we only have to read the source
1028
      --  files once.
1029
 
1030
      while Decl /= null loop
1031
 
1032
         --  Add 1 for the declaration itself
1033
 
1034
         Length := Length + References_Count (Decl, True, True, True) + 1;
1035
         Decl := Entities_HTable.Get_Next;
1036
      end loop;
1037
 
1038
      Arr := new Reference_Array (1 .. Length);
1039
      Index := Arr'First;
1040
 
1041
      Decl := Entities_HTable.Get_First;
1042
      while Decl /= null loop
1043
         Store_References (Decl, True, True, True, True, Arr.all, Index);
1044
         Decl := Entities_HTable.Get_Next;
1045
      end loop;
1046
 
1047
      Sort (Arr.all);
1048
 
1049
      --  Now traverse the whole array and find the appropriate source
1050
      --  lines.
1051
 
1052
      for R in Arr'Range loop
1053
         Ref := Arr (R);
1054
 
1055
         if Ref.File /= Current_File then
1056
            Free (Buffer);
1057
            begin
1058
               Read_File (Get_File (Ref.File, With_Dir => True), Buffer);
1059
               End_Index := Buffer'First - 1;
1060
               Line := 0;
1061
            exception
1062
               when Ada.Text_IO.Name_Error | Ada.Text_IO.End_Error =>
1063
                  Line := Natural'Last;
1064
            end;
1065
            Current_File := Ref.File;
1066
         end if;
1067
 
1068
         if Ref.Line > Line then
1069
 
1070
            --  Do not free Current_Line, it is referenced by the last
1071
            --  Ref we processed.
1072
 
1073
            loop
1074
               Index := End_Index + 1;
1075
 
1076
               loop
1077
                  End_Index := End_Index + 1;
1078
                  exit when End_Index > Buffer'Last
1079
                    or else Buffer (End_Index) = ASCII.LF;
1080
               end loop;
1081
 
1082
               --  Skip spaces at beginning of line
1083
 
1084
               while Index < End_Index and then
1085
                 (Buffer (Index) = ' ' or else Buffer (Index) = ASCII.HT)
1086
               loop
1087
                  Index := Index + 1;
1088
               end loop;
1089
 
1090
               Line := Line + 1;
1091
               exit when Ref.Line = Line;
1092
            end loop;
1093
 
1094
            Current_Line := new String'(Buffer (Index .. End_Index - 1));
1095
         end if;
1096
 
1097
         Ref.Source_Line := Current_Line;
1098
      end loop;
1099
 
1100
      Free (Buffer);
1101
      Free (Arr);
1102
   end Grep_Source_Files;
1103
 
1104
   ---------------
1105
   -- Read_File --
1106
   ---------------
1107
 
1108
   procedure Read_File
1109
     (File_Name : String;
1110
      Contents  : out GNAT.OS_Lib.String_Access)
1111
   is
1112
      Name_0 : constant String := File_Name & ASCII.NUL;
1113
      FD     : constant File_Descriptor := Open_Read (Name_0'Address, Binary);
1114
      Length : Natural;
1115
 
1116
   begin
1117
      if FD = Invalid_FD then
1118
         raise Ada.Text_IO.Name_Error;
1119
      end if;
1120
 
1121
      --  Include room for EOF char
1122
 
1123
      Length := Natural (File_Length (FD));
1124
 
1125
      declare
1126
         Buffer    : String (1 .. Length + 1);
1127
         This_Read : Integer;
1128
         Read_Ptr  : Natural := 1;
1129
 
1130
      begin
1131
         loop
1132
            This_Read := Read (FD,
1133
                               A => Buffer (Read_Ptr)'Address,
1134
                               N => Length + 1 - Read_Ptr);
1135
            Read_Ptr := Read_Ptr + Integer'Max (This_Read, 0);
1136
            exit when This_Read <= 0;
1137
         end loop;
1138
 
1139
         Buffer (Read_Ptr) := EOF;
1140
         Contents := new String'(Buffer (1 .. Read_Ptr));
1141
 
1142
         --  Things are not simple on VMS due to the plethora of file types
1143
         --  and organizations. It seems clear that there shouldn't be more
1144
         --  bytes read than are contained in the file though.
1145
 
1146
         if (Hostparm.OpenVMS and then Read_Ptr > Length + 1)
1147
           or else (not Hostparm.OpenVMS and then Read_Ptr /= Length + 1)
1148
         then
1149
            raise Ada.Text_IO.End_Error;
1150
         end if;
1151
 
1152
         Close (FD);
1153
      end;
1154
   end Read_File;
1155
 
1156
   -----------------------
1157
   -- Longest_File_Name --
1158
   -----------------------
1159
 
1160
   function Longest_File_Name return Natural is
1161
   begin
1162
      return Longest_File_Name_In_Table;
1163
   end Longest_File_Name;
1164
 
1165
   -----------
1166
   -- Match --
1167
   -----------
1168
 
1169
   function Match
1170
     (File   : File_Reference;
1171
      Line   : Natural;
1172
      Column : Natural)
1173
      return   Boolean
1174
   is
1175
      Ref : Ref_In_File_Ptr := File.Lines;
1176
 
1177
   begin
1178
      while Ref /= null loop
1179
         if (Ref.Line = 0 or else Ref.Line = Line)
1180
           and then (Ref.Column = 0 or else Ref.Column = Column)
1181
         then
1182
            return True;
1183
         end if;
1184
 
1185
         Ref := Ref.Next;
1186
      end loop;
1187
 
1188
      return False;
1189
   end Match;
1190
 
1191
   -----------
1192
   -- Match --
1193
   -----------
1194
 
1195
   function Match (Decl : Declaration_Reference) return Boolean is
1196
   begin
1197
      return Decl.Match;
1198
   end Match;
1199
 
1200
   ----------
1201
   -- Next --
1202
   ----------
1203
 
1204
   function Next (E : File_Reference) return File_Reference is
1205
   begin
1206
      return E.Next;
1207
   end Next;
1208
 
1209
   function Next (E : Declaration_Reference) return Declaration_Reference is
1210
   begin
1211
      return E.Next;
1212
   end Next;
1213
 
1214
   ------------------
1215
   -- Next_Obj_Dir --
1216
   ------------------
1217
 
1218
   function Next_Obj_Dir return String is
1219
      First : constant Integer := Directories.Obj_Dir_Index;
1220
      Last  : Integer;
1221
 
1222
   begin
1223
      Last := Directories.Obj_Dir_Index;
1224
 
1225
      if Last > Directories.Obj_Dir_Length then
1226
         return String'(1 .. 0 => ' ');
1227
      end if;
1228
 
1229
      while Directories.Obj_Dir (Last) /= Path_Separator loop
1230
         Last := Last + 1;
1231
      end loop;
1232
 
1233
      Directories.Obj_Dir_Index := Last + 1;
1234
      Directories.Last_Obj_Dir_Start := First;
1235
      return Directories.Obj_Dir (First .. Last - 1);
1236
   end Next_Obj_Dir;
1237
 
1238
   -------------------------
1239
   -- Next_Unvisited_File --
1240
   -------------------------
1241
 
1242
   function Next_Unvisited_File return File_Reference is
1243
      procedure Unchecked_Free is new Ada.Unchecked_Deallocation
1244
        (Unvisited_Files_Record, Unvisited_Files_Access);
1245
 
1246
      Ref : File_Reference;
1247
      Tmp : Unvisited_Files_Access;
1248
 
1249
   begin
1250
      if Unvisited_Files = null then
1251
         return Empty_File;
1252
      else
1253
         Tmp := Unvisited_Files;
1254
         Ref := Unvisited_Files.File;
1255
         Unvisited_Files := Unvisited_Files.Next;
1256
         Unchecked_Free (Tmp);
1257
         return Ref;
1258
      end if;
1259
   end Next_Unvisited_File;
1260
 
1261
   ----------------------
1262
   -- Parse_Gnatls_Src --
1263
   ----------------------
1264
 
1265
   function Parse_Gnatls_Src return String is
1266
      Length : Natural;
1267
 
1268
   begin
1269
      Length := 0;
1270
      for J in 1 .. Osint.Nb_Dir_In_Src_Search_Path loop
1271
         if Osint.Dir_In_Src_Search_Path (J)'Length = 0 then
1272
            Length := Length + 2;
1273
         else
1274
            Length := Length + Osint.Dir_In_Src_Search_Path (J)'Length + 1;
1275
         end if;
1276
      end loop;
1277
 
1278
      declare
1279
         Result : String (1 .. Length);
1280
         L      : Natural;
1281
 
1282
      begin
1283
         L := Result'First;
1284
         for J in 1 .. Osint.Nb_Dir_In_Src_Search_Path loop
1285
            if Osint.Dir_In_Src_Search_Path (J)'Length = 0 then
1286
               Result (L .. L + 1) := "." & Path_Separator;
1287
               L := L + 2;
1288
 
1289
            else
1290
               Result (L .. L + Osint.Dir_In_Src_Search_Path (J)'Length - 1) :=
1291
                 Osint.Dir_In_Src_Search_Path (J).all;
1292
               L := L + Osint.Dir_In_Src_Search_Path (J)'Length;
1293
               Result (L) := Path_Separator;
1294
               L := L + 1;
1295
            end if;
1296
         end loop;
1297
 
1298
         return Result;
1299
      end;
1300
   end Parse_Gnatls_Src;
1301
 
1302
   ----------------------
1303
   -- Parse_Gnatls_Obj --
1304
   ----------------------
1305
 
1306
   function Parse_Gnatls_Obj return String is
1307
      Length : Natural;
1308
 
1309
   begin
1310
      Length := 0;
1311
      for J in 1 .. Osint.Nb_Dir_In_Obj_Search_Path loop
1312
         if Osint.Dir_In_Obj_Search_Path (J)'Length = 0 then
1313
            Length := Length + 2;
1314
         else
1315
            Length := Length + Osint.Dir_In_Obj_Search_Path (J)'Length + 1;
1316
         end if;
1317
      end loop;
1318
 
1319
      declare
1320
         Result : String (1 .. Length);
1321
         L      : Natural;
1322
 
1323
      begin
1324
         L := Result'First;
1325
         for J in 1 .. Osint.Nb_Dir_In_Obj_Search_Path loop
1326
            if Osint.Dir_In_Obj_Search_Path (J)'Length = 0 then
1327
               Result (L .. L + 1) := "." & Path_Separator;
1328
               L := L + 2;
1329
            else
1330
               Result (L .. L + Osint.Dir_In_Obj_Search_Path (J)'Length - 1) :=
1331
                 Osint.Dir_In_Obj_Search_Path (J).all;
1332
               L := L + Osint.Dir_In_Obj_Search_Path (J)'Length;
1333
               Result (L) := Path_Separator;
1334
               L := L + 1;
1335
            end if;
1336
         end loop;
1337
 
1338
         return Result;
1339
      end;
1340
   end Parse_Gnatls_Obj;
1341
 
1342
   -------------------
1343
   -- Reset_Obj_Dir --
1344
   -------------------
1345
 
1346
   procedure Reset_Obj_Dir is
1347
   begin
1348
      Directories.Obj_Dir_Index := 1;
1349
   end Reset_Obj_Dir;
1350
 
1351
   -----------------------
1352
   -- Set_Default_Match --
1353
   -----------------------
1354
 
1355
   procedure Set_Default_Match (Value : Boolean) is
1356
   begin
1357
      Default_Match := Value;
1358
   end Set_Default_Match;
1359
 
1360
   ----------
1361
   -- Free --
1362
   ----------
1363
 
1364
   procedure Free (Str : in out Cst_String_Access) is
1365
      function Convert is new Ada.Unchecked_Conversion
1366
        (Cst_String_Access, GNAT.OS_Lib.String_Access);
1367
 
1368
      S : GNAT.OS_Lib.String_Access := Convert (Str);
1369
 
1370
   begin
1371
      Free (S);
1372
      Str := null;
1373
   end Free;
1374
 
1375
   ---------------------
1376
   -- Reset_Directory --
1377
   ---------------------
1378
 
1379
   procedure Reset_Directory (File : File_Reference) is
1380
   begin
1381
      Free (File.Dir);
1382
   end Reset_Directory;
1383
 
1384
   -------------------
1385
   -- Set_Unvisited --
1386
   -------------------
1387
 
1388
   procedure Set_Unvisited (File_Ref : File_Reference) is
1389
      F : constant String := Get_File (File_Ref, With_Dir => False);
1390
 
1391
   begin
1392
      File_Ref.Visited := False;
1393
 
1394
      --  ??? Do not add a source file to the list. This is true at
1395
      --  least for gnatxref, and probably for gnatfind as well
1396
 
1397
      if F'Length > 4
1398
        and then F (F'Last - 3 .. F'Last) = "." & Osint.ALI_Suffix.all
1399
      then
1400
         Unvisited_Files := new Unvisited_Files_Record'
1401
           (File => File_Ref,
1402
            Next => Unvisited_Files);
1403
      end if;
1404
   end Set_Unvisited;
1405
 
1406
   ----------------------
1407
   -- Get_Declarations --
1408
   ----------------------
1409
 
1410
   function Get_Declarations
1411
     (Sorted : Boolean := True)
1412
      return   Declaration_Array_Access
1413
   is
1414
      Arr   : constant Declaration_Array_Access :=
1415
                new Declaration_Array (1 .. Entities_Count);
1416
      Decl  : Declaration_Reference := Entities_HTable.Get_First;
1417
      Index : Natural               := Arr'First;
1418
      Tmp   : Declaration_Reference;
1419
 
1420
      procedure Move (From : Natural; To : Natural);
1421
      function Lt (Op1, Op2 : Natural) return Boolean;
1422
      --  See GNAT.Heap_Sort_G
1423
 
1424
      --------
1425
      -- Lt --
1426
      --------
1427
 
1428
      function Lt (Op1, Op2 : Natural) return Boolean is
1429
      begin
1430
         if Op1 = 0 then
1431
            return Is_Less_Than (Tmp, Arr (Op2));
1432
         elsif Op2 = 0 then
1433
            return Is_Less_Than (Arr (Op1), Tmp);
1434
         else
1435
            return Is_Less_Than (Arr (Op1), Arr (Op2));
1436
         end if;
1437
      end Lt;
1438
 
1439
      ----------
1440
      -- Move --
1441
      ----------
1442
 
1443
      procedure Move (From : Natural; To : Natural) is
1444
      begin
1445
         if To = 0 then
1446
            Tmp := Arr (From);
1447
         elsif From = 0 then
1448
            Arr (To) := Tmp;
1449
         else
1450
            Arr (To) := Arr (From);
1451
         end if;
1452
      end Move;
1453
 
1454
      package Decl_Sort is new GNAT.Heap_Sort_G (Move, Lt);
1455
 
1456
   --  Start of processing for Get_Declarations
1457
 
1458
   begin
1459
      while Decl /= null loop
1460
         Arr (Index) := Decl;
1461
         Index := Index + 1;
1462
         Decl := Entities_HTable.Get_Next;
1463
      end loop;
1464
 
1465
      if Sorted and then Arr'Length /= 0 then
1466
         Decl_Sort.Sort (Entities_Count);
1467
      end if;
1468
 
1469
      return Arr;
1470
   end Get_Declarations;
1471
 
1472
   ----------------------
1473
   -- References_Count --
1474
   ----------------------
1475
 
1476
   function References_Count
1477
     (Decl       : Declaration_Reference;
1478
      Get_Reads  : Boolean := False;
1479
      Get_Writes : Boolean := False;
1480
      Get_Bodies : Boolean := False)
1481
      return       Natural
1482
   is
1483
      function List_Length (E : Reference) return Natural;
1484
      --  Return the number of references in E
1485
 
1486
      -----------------
1487
      -- List_Length --
1488
      -----------------
1489
 
1490
      function List_Length (E : Reference) return Natural is
1491
         L  : Natural := 0;
1492
         E1 : Reference := E;
1493
 
1494
      begin
1495
         while E1 /= null loop
1496
            L := L + 1;
1497
            E1 := E1.Next;
1498
         end loop;
1499
 
1500
         return L;
1501
      end List_Length;
1502
 
1503
      Length : Natural := 0;
1504
 
1505
   --  Start of processing for References_Count
1506
 
1507
   begin
1508
      if Get_Reads then
1509
         Length := List_Length (Decl.Ref_Ref);
1510
      end if;
1511
 
1512
      if Get_Writes then
1513
         Length := Length + List_Length (Decl.Modif_Ref);
1514
      end if;
1515
 
1516
      if Get_Bodies then
1517
         Length := Length + List_Length (Decl.Body_Ref);
1518
      end if;
1519
 
1520
      return Length;
1521
   end References_Count;
1522
 
1523
   ----------------------
1524
   -- Store_References --
1525
   ----------------------
1526
 
1527
   procedure Store_References
1528
     (Decl            : Declaration_Reference;
1529
      Get_Writes      : Boolean := False;
1530
      Get_Reads       : Boolean := False;
1531
      Get_Bodies      : Boolean := False;
1532
      Get_Declaration : Boolean := False;
1533
      Arr             : in out Reference_Array;
1534
      Index           : in out Natural)
1535
   is
1536
      procedure Add (List : Reference);
1537
      --  Add all the references in List to Arr
1538
 
1539
      ---------
1540
      -- Add --
1541
      ---------
1542
 
1543
      procedure Add (List : Reference) is
1544
         E : Reference := List;
1545
      begin
1546
         while E /= null loop
1547
            Arr (Index) := E;
1548
            Index := Index + 1;
1549
            E := E.Next;
1550
         end loop;
1551
      end Add;
1552
 
1553
   --  Start of processing for Store_References
1554
 
1555
   begin
1556
      if Get_Declaration then
1557
         Add (Decl.Decl);
1558
      end if;
1559
 
1560
      if Get_Reads then
1561
         Add (Decl.Ref_Ref);
1562
      end if;
1563
 
1564
      if Get_Writes then
1565
         Add (Decl.Modif_Ref);
1566
      end if;
1567
 
1568
      if Get_Bodies then
1569
         Add (Decl.Body_Ref);
1570
      end if;
1571
   end Store_References;
1572
 
1573
   --------------------
1574
   -- Get_References --
1575
   --------------------
1576
 
1577
   function Get_References
1578
     (Decl : Declaration_Reference;
1579
      Get_Reads  : Boolean := False;
1580
      Get_Writes : Boolean := False;
1581
      Get_Bodies : Boolean := False)
1582
      return       Reference_Array_Access
1583
   is
1584
      Length : constant Natural :=
1585
                 References_Count (Decl, Get_Reads, Get_Writes, Get_Bodies);
1586
 
1587
      Arr : constant Reference_Array_Access :=
1588
              new Reference_Array (1 .. Length);
1589
 
1590
      Index : Natural := Arr'First;
1591
 
1592
   begin
1593
      Store_References
1594
        (Decl            => Decl,
1595
         Get_Writes      => Get_Writes,
1596
         Get_Reads       => Get_Reads,
1597
         Get_Bodies      => Get_Bodies,
1598
         Get_Declaration => False,
1599
         Arr             => Arr.all,
1600
         Index           => Index);
1601
 
1602
      if Arr'Length /= 0 then
1603
         Sort (Arr.all);
1604
      end if;
1605
 
1606
      return Arr;
1607
   end Get_References;
1608
 
1609
   ----------
1610
   -- Free --
1611
   ----------
1612
 
1613
   procedure Free (Arr : in out Reference_Array_Access) is
1614
      procedure Internal is new Ada.Unchecked_Deallocation
1615
        (Reference_Array, Reference_Array_Access);
1616
   begin
1617
      Internal (Arr);
1618
   end Free;
1619
 
1620
   ------------------
1621
   -- Is_Parameter --
1622
   ------------------
1623
 
1624
   function Is_Parameter (Decl : Declaration_Reference) return Boolean is
1625
   begin
1626
      return Decl.Is_Parameter;
1627
   end Is_Parameter;
1628
 
1629
end Xr_Tabls;

powered by: WebSVN 2.1.0

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