1
-------------------------------------------------------------------------------
3
-- This file is part of AdaBrowse.
5
-- <STRONG>Copyright (c) 2002 by Thomas Wolf.</STRONG>
7
-- AdaBrowse is free software; you can redistribute it and/or modify it
8
-- under the terms of the GNU General Public License as published by the
9
-- Free Software Foundation; either version 2, or (at your option) any
10
-- later version. AdaBrowse is distributed in the hope that it will be
11
-- useful, but <EM>without any warranty</EM>; without even the implied
12
-- warranty of <EM>merchantability or fitness for a particular purpose.</EM>
13
-- See the GNU General Public License for more details. You should have
14
-- received a copy of the GNU General Public License with this distribution,
15
-- see file "<A HREF="GPL.txt">GPL.txt</A>". If not, write to the Free
16
-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21
-- Author:</STRONG><DD>
23
-- <ADDRESS><A HREF="mailto:twolf@acm.org">twolf@acm.org</A></ADDRESS></DL>
26
-- Purpose:</STRONG><DD>
27
-- Abstract root type for the various output producers (HTML, XML, DocBook,
33
-- 22-JUL-2002 TW Initial version.
34
-- 30-JUL-2003 TW Complete rewrite of the indexing stuff.
36
-------------------------------------------------------------------------------
43
with Asis.Declarations;
55
package body AD.Printers is
57
use Asis.Declarations;
63
----------------------------------------------------------------------------
66
(Pos : in Asis2.Spans.Position;
72
return Trim (Asis.Text.Line_Number'Image (Pos.Line)) &
74
Trim (Asis.Text.Character_Position'Image (Pos.Column));
76
return Trim (Asis.Text.Line_Number'Image (Pos.Line));
80
----------------------------------------------------------------------------
82
procedure Set_Line_Only
85
Full_Crossrefs := False;
87
("-l option given: cross-references use only the line number.");
90
----------------------------------------------------------------------------
92
function Get_Item_Kind
93
(Item : in Asis.Element)
97
(Decl : in Asis.Declaration)
100
Encl : Asis.Element := Decl;
102
-- Loop until we either hit a nil element or a declaration.
104
Encl := Enclosing_Element (Encl);
105
exit when Is_Nil (Encl);
106
case Declaration_Kind (Encl) is
107
when Not_A_Declaration =>
109
when A_Protected_Type_Declaration |
110
A_Single_Protected_Declaration |
111
A_Task_Type_Declaration |
112
A_Single_Task_Declaration =>
122
case Declaration_Kind (Item) is
123
when Not_A_Declaration =>
124
-- It had better be a pragma! (What about rep clauses?)
125
-- We also have use clauses here...
126
case Element_Kind (Item) is
127
when Asis.A_Pragma =>
128
return AD.Printers.A_Pragma;
129
when Asis.A_Clause =>
130
case Clause_Kind (Item) is
131
when A_Use_Package_Clause =>
133
when Asis.A_Use_Type_Clause =>
134
return AD.Printers.A_Use_Type_Clause;
142
when A_Procedure_Declaration =>
144
return A_Protected_Procedure;
149
when A_Function_Declaration =>
151
return A_Protected_Function;
156
when An_Entry_Declaration =>
159
when A_Package_Declaration =>
162
when A_Generic_Package_Declaration =>
164
Visible_Stuff : constant Declaration_List :=
165
Visible_Part_Declarative_Items (Item);
167
if Visible_Stuff'Last < Visible_Stuff'First then
168
return A_Generic_Signature_Package;
170
return A_Generic_Package;
174
when A_Generic_Procedure_Declaration =>
175
return A_Generic_Procedure;
177
when A_Generic_Function_Declaration =>
178
return A_Generic_Function;
180
when Asis.A_Package_Instantiation =>
181
return AD.Printers.A_Package_Instantiation;
183
when Asis.A_Procedure_Instantiation =>
184
return AD.Printers.A_Procedure_Instantiation;
186
when Asis.A_Function_Instantiation =>
187
return AD.Printers.A_Function_Instantiation;
189
when A_Package_Renaming_Declaration =>
190
return A_Package_Renaming;
192
when A_Procedure_Renaming_Declaration =>
193
return A_Procedure_Renaming;
195
when A_Function_Renaming_Declaration =>
196
return A_Function_Renaming;
198
when A_Generic_Package_Renaming_Declaration =>
199
return A_Generic_Package_Renaming;
201
when A_Generic_Procedure_Renaming_Declaration =>
202
return A_Generic_Procedure_Renaming;
204
when A_Generic_Function_Renaming_Declaration =>
205
return A_Generic_Function_Renaming;
207
when A_Task_Type_Declaration =>
210
when A_Single_Task_Declaration =>
213
when A_Protected_Type_Declaration =>
214
return A_Protected_Type;
216
when A_Single_Protected_Declaration =>
217
return A_Protected_Object;
219
when A_Subtype_Declaration =>
222
when An_Ordinary_Type_Declaration |
223
An_Incomplete_Type_Declaration |
224
A_Private_Type_Declaration |
225
A_Private_Extension_Declaration =>
228
when A_Variable_Declaration =>
231
when A_Constant_Declaration |
232
An_Integer_Number_Declaration |
233
A_Real_Number_Declaration =>
236
when A_Deferred_Constant_Declaration =>
237
return A_Deferred_Constant;
239
when An_Object_Renaming_Declaration =>
240
return An_Object_Renaming;
242
when An_Exception_Renaming_Declaration =>
243
return An_Exception_Renaming;
245
when An_Exception_Declaration =>
255
(Self : access Printer'Class;
259
Tmp : String (Line'First ..
260
Line'Last + AD.Syntax.Max_Keyword_Length + 1);
261
Last_Char : Character;
266
-- 'Tmp' is a lower-case copy of 'Line' with extra padding characters at
267
-- the end. It serves to simplify 'Find_Keyword': it doesn't have to
268
-- worry about casing, and it can also ignore overflow problems.
269
for I in Line'Range loop
270
Tmp (I) := To_Lower (Line (I));
272
for I in Line'Last + 1 .. Tmp'Last loop
277
while I <= Line'Last loop
278
AD.Syntax.Find_Keyword
279
(Tmp (I .. Tmp'Last), Last_Char, Line'Last, Start, Stop);
281
Write (Self, Line (I .. Line'Last));
285
Write (Self, Line (I .. Start - 1));
287
if Tmp (Start .. Stop) = "--" then
288
-- We have a comment!!
289
Write_Comment (Self, Line (Start .. Line'Last));
291
elsif Tmp (Start) = '"' or Tmp (Start) = ''' then
292
-- A string or character literal.
293
Write_Literal (Self, Line (Start .. Stop));
295
-- A real keyword. Write 'Tmp', not 'Line': this makes all
296
-- keywords lowercase for free!
297
Write_Keyword (Self, Tmp (Start .. Stop));
299
Last_Char := Tmp (Stop); I := Stop + 1;
303
----------------------------------------------------------------------------
306
(Self : in out Real_Printer;
307
Mode : in AD.Options.File_Handling;
308
File_Name : in String;
309
Use_Default : in Boolean := True)
311
use type Ada.Text_IO.File_Access;
312
use type AD.Options.File_Handling;
315
(File : in out Ada.Text_IO.File_Type;
319
new Util.Files.Open_G
320
(Ada.Text_IO.File_Type, Ada.Text_IO.File_Mode,
321
Ada.Text_IO.Open, Ada.Text_IO.Create);
323
if not AD.Options.Allow_Overwrite and then
324
AD.File_Ops.Exists (Name)
326
Ada.Exceptions.Raise_Exception
327
(Cannot_Overwrite'Identity,
328
"Mustn't write to file """ & Name & """.");
331
Open (File, Ada.Text_IO.Out_File, Name);
334
Ada.Exceptions.Raise_Exception
335
(Open_Failed'Identity,
336
"Cannot write to file """ & Name & """.");
341
if Self.F /= null then Close_File (Self); end if;
345
Name : constant String := AD.Options.Output_Name;
349
Self.F := Ada.Text_IO.Current_Output;
352
if Name'Last >= Name'First and then
353
Mode = AD.Options.Single_File
355
-- Not stdout: first try 'Name', if that fails, try 'File_Name'
358
Util.Pathes.Replace_Extension
359
(Name, Get_Suffix (Real_Printer'Class (Self))));
362
if File_Name'Last >= File_Name'First then
364
(Ada.Exceptions.Exception_Message (E));
372
if not Ada.Text_IO.Is_Open (Self.File) then
373
-- Ok, it's not stdout, and either we have no name or we failed to
374
-- open file 'Name', or we're in multi-file mode: open a file
375
-- 'File_Name' in the specified directory.
376
if File_Name = "-" then
377
Self.F := Ada.Text_IO.Current_Output;
380
if Util.Pathes.Path (File_Name) /= "" then
381
-- The given File_Name *does* have a path itself: use that!
384
Util.Pathes.Replace_Extension
385
(File_Name, Get_Suffix (Real_Printer'Class (Self))));
387
-- 'File_Name' is a simple file: prepend the default output
392
(AD.Options.Output_Directory,
393
Util.Pathes.Replace_Extension
394
(File_Name, Get_Suffix (Real_Printer'Class (Self)))));
397
-- Here, Self.File is open.
398
Self.F := Ada.Text_IO.File_Access'(Self.File'Unchecked_Access);
402
(Self : in Real_Printer)
405
use type Ada.Text_IO.File_Access;
407
return Self.F /= null;
411
(Self : in out Real_Printer)
414
if Ada.Text_IO.Is_Open (Self.File) then
415
Ada.Text_IO.Close (Self.File);
421
(Self : access Real_Printer;
425
if Self.Use_Buffer then
426
Util.Text.Append (Self.Buffer, Ch);
428
Ada.Text_IO.Put (Self.F.all, Ch);
433
(Self : access Real_Printer;
437
if Self.Use_Buffer then
438
Util.Text.Append (Self.Buffer, S);
440
Ada.Text_IO.Put (Self.F.all, S);
445
(Self : access Real_Printer;
449
Put_Line (Self.all, S);
453
(Self : in out Real_Printer;
458
if Self.Use_Buffer then
459
Util.Text.Append (Self.Buffer, S & ASCII.LF);
461
Ada.Text_IO.Put_Line (Self.F.all, S);
466
(Self : access Real_Printer;
467
N : in Positive := 1)
470
if Self.Use_Buffer then
472
Line_Feeds : constant String (1 .. N) := (others => ASCII.LF);
474
Util.Text.Append (Self.Buffer, Line_Feeds);
477
Ada.Text_IO.New_Line (Self.F.all, Ada.Text_IO.Positive_Count (N));
482
(Self : in out Real_Printer)
491
----------------------------------------------------------------------------
494
(Left, Right : in Printer_Ref)
500
elsif Right = null then
504
P : constant Printer_Ref := new Composer;
506
Composer (P.all).Left := Left;
507
Composer (P.all).Right := Right;
513
----------------------------------------------------------------------------
520
return Is_Open (Self.Left.all) or else Is_Open (Self.Right.all);
524
(Self : in out Composer)
527
if Self.Left /= null then
530
if Self.Right /= null then
533
-- A composer has no open files, so no need to close the output!
537
(Self : access Composer;
538
Unit_Kind : in Item_Kind;
539
Unit_Name : in Wide_String;
540
Is_Private : in Boolean;
541
XRef : in AD.Crossrefs.Cross_Reference)
544
Open_Unit (Self.Left, Unit_Kind, Unit_Name, Is_Private, XRef);
545
Self.Left_Open := Is_Open (Self.Left.all);
546
Open_Unit (Self.Right, Unit_Kind, Unit_Name, Is_Private, XRef);
547
Self.Right_Open := Is_Open (Self.Right.all);
551
(Self : access Composer)
554
if Self.Left_Open then
555
Close_Unit (Self.Left);
557
if Self.Right_Open then
558
Close_Unit (Self.Right);
562
procedure Write_Comment
563
(Self : access Composer;
564
Lines : in Asis.Text.Line_List)
567
if Self.Left_Open then
568
Write_Comment (Self.Left, Lines);
570
if Self.Right_Open then
571
Write_Comment (Self.Right, Lines);
575
procedure Open_Section
576
(Self : access Composer;
577
Section : in Section_Type)
580
if Self.Left_Open then
581
Open_Section (Self.Left, Section);
583
if Self.Right_Open then
584
Open_Section (Self.Right, Section);
588
procedure Close_Section
589
(Self : access Composer;
590
Section : in Section_Type)
593
if Self.Left_Open then
594
Close_Section (Self.Left, Section);
596
if Self.Right_Open then
597
Close_Section (Self.Right, Section);
602
(Self : access Composer;
603
XRef : in AD.Crossrefs.Cross_Reference;
604
Kind : in Item_Kind := Not_An_Item;
605
Name : in Wide_String := "")
608
if Self.Left_Open then
609
Open_Item (Self.Left, XRef, Kind, Name);
611
if Self.Right_Open then
612
Open_Item (Self.Right, XRef, Kind, Name);
617
(Self : access Composer;
618
Is_Last : in Boolean := False)
621
if Self.Left_Open then
622
Close_Item (Self.Left, Is_Last);
624
if Self.Right_Open then
625
Close_Item (Self.Right, Is_Last);
629
procedure Other_Declaration
630
(Self : access Composer;
631
XRef : in AD.Crossrefs.Cross_Reference;
635
if Self.Left_Open then
636
Other_Declaration (Self.Left, XRef, Text);
638
if Self.Right_Open then
639
Other_Declaration (Self.Right, XRef, Text);
641
end Other_Declaration;
643
procedure Open_Container
644
(Self : access Composer;
645
XRef : in AD.Crossrefs.Cross_Reference;
647
Name : in Wide_String := "")
650
if Self.Left_Open then
651
Open_Container (Self.Left, XRef, Kind, Name);
653
if Self.Right_Open then
654
Open_Container (Self.Right, XRef, Kind, Name);
658
procedure Close_Container
659
(Self : access Composer;
660
Is_Last : in Boolean := False)
663
if Self.Left_Open then
664
Close_Container (Self.Left, Is_Last);
666
if Self.Right_Open then
667
Close_Container (Self.Right, Is_Last);
672
(Self : access Composer;
674
Is_Private : in Boolean;
675
XRef : in AD.Crossrefs.Cross_Reference)
678
if Self.Left_Open then
679
Add_Child (Self.Left, Kind, Is_Private, XRef);
681
if Self.Right_Open then
682
Add_Child (Self.Right, Kind, Is_Private, XRef);
686
procedure Add_Exception
687
(Self : access Composer;
688
XRef : in AD.Crossrefs.Cross_Reference)
691
if Self.Left_Open then
692
Add_Exception (Self.Left, XRef);
694
if Self.Right_Open then
695
Add_Exception (Self.Right, XRef);
700
(Self : access Composer;
701
XRef : in AD.Crossrefs.Cross_Reference)
704
if Self.Left_Open then
705
Type_Name (Self.Left, XRef);
707
if Self.Right_Open then
708
Type_Name (Self.Right, XRef);
713
(Self : access Composer;
717
if Self.Left_Open then
718
Type_Kind (Self.Left, Info);
720
if Self.Right_Open then
721
Type_Kind (Self.Right, Info);
725
procedure Parent_Type
726
(Self : access Composer;
727
XRef : in AD.Crossrefs.Cross_Reference)
730
if Self.Left_Open then
731
Parent_Type (Self.Left, XRef);
733
if Self.Right_Open then
734
Parent_Type (Self.Right, XRef);
738
procedure Open_Operation_List
739
(Self : access Composer;
740
Kind : in Operation_Kind)
743
if Self.Left_Open then
744
Open_Operation_List (Self.Left, Kind);
746
if Self.Right_Open then
747
Open_Operation_List (Self.Right, Kind);
749
end Open_Operation_List;
751
procedure Close_Operation_List
752
(Self : access Composer)
755
if Self.Left_Open then
756
Close_Operation_List (Self.Left);
758
if Self.Right_Open then
759
Close_Operation_List (Self.Right);
761
end Close_Operation_List;
763
procedure Add_Type_Operation
764
(Self : access Composer;
765
XRef : in AD.Crossrefs.Cross_Reference)
768
if Self.Left_Open then
769
Add_Type_Operation (Self.Left, XRef);
771
if Self.Right_Open then
772
Add_Type_Operation (Self.Right, XRef);
774
end Add_Type_Operation;
776
procedure Add_Private
777
(Self : access Composer;
778
For_Package : in Boolean)
781
if Self.Left_Open then
782
Add_Private (Self.Left, For_Package);
784
if Self.Right_Open then
785
Add_Private (Self.Right, For_Package);
789
procedure Open_Anchor
790
(Self : access Composer;
791
XRef : in AD.Crossrefs.Cross_Reference)
794
if Self.Left_Open then
795
Open_Anchor (Self.Left, XRef);
797
if Self.Right_Open then
798
Open_Anchor (Self.Right, XRef);
802
procedure Close_Anchor
803
(Self : access Composer)
806
if Self.Left_Open then
807
Close_Anchor (Self.Left);
809
if Self.Right_Open then
810
Close_Anchor (Self.Right);
815
(Self : access Composer;
816
XRef : in AD.Crossrefs.Cross_Reference)
819
if Self.Left_Open then
820
Open_XRef (Self.Left, XRef);
822
if Self.Right_Open then
823
Open_XRef (Self.Right, XRef);
828
(Self : access Composer)
831
if Self.Left_Open then
832
Close_XRef (Self.Left);
834
if Self.Right_Open then
835
Close_XRef (Self.Right);
840
(Self : access Composer;
841
XRef : in AD.Crossrefs.Cross_Reference;
842
Code : in Boolean := True;
843
Is_Index : in Boolean := False)
846
if Self.Left_Open then
847
Put_XRef (Self.Left, XRef, Code, Is_Index);
849
if Self.Right_Open then
850
Put_XRef (Self.Right, XRef, Code, Is_Index);
854
procedure Inline_Error
855
(Self : access Composer;
859
if Self.Left_Open then
860
Inline_Error (Self.Left, Msg);
862
if Self.Right_Open then
863
Inline_Error (Self.Right, Msg);
867
----------------------------------------------------------------------------
868
-- Basic inline elements.
870
procedure Write_Keyword
871
(Self : access Composer;
875
if Self.Left_Open then
876
Write_Keyword (Self.Left, S);
878
if Self.Right_Open then
879
Write_Keyword (Self.Right, S);
883
procedure Write_Literal
884
(Self : access Composer;
888
if Self.Left_Open then
889
Write_Literal (Self.Left, S);
891
if Self.Right_Open then
892
Write_Literal (Self.Right, S);
896
procedure Write_Attribute
897
(Self : access Composer;
901
if Self.Left_Open then
902
Write_Attribute (Self.Left, S);
904
if Self.Right_Open then
905
Write_Attribute (Self.Right, S);
909
procedure Write_Comment
910
(Self : access Composer;
914
if Self.Left_Open then
915
Write_Comment (Self.Left, S);
917
if Self.Right_Open then
918
Write_Comment (Self.Right, S);
923
(Self : access Composer;
927
if Self.Left_Open then
928
Write (Self.Left, S);
930
if Self.Right_Open then
931
Write (Self.Right, S);
935
procedure Write_Plain
936
(Self : access Composer;
940
if Self.Left_Open then
941
Write_Plain (Self.Left, S);
943
if Self.Right_Open then
944
Write_Plain (Self.Right, S);
949
(Self : access Composer;
953
if Self.Left_Open then
954
Write_Code (Self.Left, S);
956
if Self.Right_Open then
957
Write_Code (Self.Right, S);
962
(Self : access Composer;
963
N : in Positive := 1)
966
if Self.Left_Open then
967
New_Line (Self.Left, N);
969
if Self.Right_Open then
970
New_Line (Self.Right, N);
975
(Self : access Composer;
976
File_Name : in String;
978
Present : in Ada.Strings.Maps.Character_Set)
981
Open_Index (Self.Left, File_Name, Title, Present);
982
Self.Left_Open := Is_Open (Self.Left.all);
983
Open_Index (Self.Right, File_Name, Title, Present);
984
Self.Right_Open := Is_Open (Self.Right.all);
987
procedure Close_Index
988
(Self : access Composer)
991
Close_Index (Self.Left);
992
Close_Index (Self.Right);
996
(Self : access Composer;
997
File_Name : in String;
1001
if Self.Left_Open then
1002
XRef_Index (Self.Left, File_Name, Title);
1004
if Self.Right_Open then
1005
XRef_Index (Self.Right, File_Name, Title);
1009
procedure Open_Char_Section
1010
(Self : access Composer;
1011
Char : in Character)
1014
if Self.Left_Open then
1015
Open_Char_Section (Self.Left, Char);
1017
if Self.Right_Open then
1018
Open_Char_Section (Self.Right, Char);
1020
end Open_Char_Section;
1022
procedure Close_Char_Section
1023
(Self : access Composer)
1026
if Self.Left_Open then
1027
Close_Char_Section (Self.Left);
1029
if Self.Right_Open then
1030
Close_Char_Section (Self.Right);
1032
end Close_Char_Section;
1034
procedure Open_Index_Structure
1035
(Self : access Composer)
1038
if Self.Left_Open then
1039
Open_Index_Structure (Self.Left);
1041
if Self.Right_Open then
1042
Open_Index_Structure (Self.Right);
1044
end Open_Index_Structure;
1046
procedure Close_Index_Structure
1047
(Self : access Composer)
1050
if Self.Left_Open then
1051
Close_Index_Structure (Self.Left);
1053
if Self.Right_Open then
1054
Close_Index_Structure (Self.Right);
1056
end Close_Index_Structure;
1058
procedure Open_Index_Item
1059
(Self : access Composer)
1062
if Self.Left_Open then
1063
Open_Index_Item (Self.Left);
1065
if Self.Right_Open then
1066
Open_Index_Item (Self.Right);
1068
end Open_Index_Item;
1070
procedure Close_Index_Item
1071
(Self : access Composer)
1074
if Self.Left_Open then
1075
Close_Index_Item (Self.Left);
1077
if Self.Right_Open then
1078
Close_Index_Item (Self.Right);
1080
end Close_Index_Item;