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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 706 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                                C L E A N                                 --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 2003-2011, 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 ALI;      use ALI;
27
with Csets;
28
with Makeutl;  use Makeutl;
29
with MLib.Tgt; use MLib.Tgt;
30
with Namet;    use Namet;
31
with Opt;      use Opt;
32
with Osint;    use Osint;
33
with Osint.M;  use Osint.M;
34
with Prj;      use Prj;
35
with Prj.Env;
36
with Prj.Ext;
37
with Prj.Pars;
38
with Prj.Tree; use Prj.Tree;
39
with Prj.Util; use Prj.Util;
40
with Sdefault;
41
with Snames;
42
with Switch;   use Switch;
43
with Table;
44
with Targparm; use Targparm;
45
with Types;    use Types;
46
 
47
with Ada.Command_Line;          use Ada.Command_Line;
48
 
49
with GNAT.Directory_Operations; use GNAT.Directory_Operations;
50
with GNAT.IO;                   use GNAT.IO;
51
with GNAT.OS_Lib;               use GNAT.OS_Lib;
52
 
53
package body Clean is
54
 
55
   Initialized : Boolean := False;
56
   --  Set to True by the first call to Initialize.
57
   --  To avoid reinitialization of some packages.
58
 
59
   --  Suffixes of various files
60
 
61
   Assembly_Suffix : constant String := ".s";
62
   ALI_Suffix      : constant String := ".ali";
63
   Tree_Suffix     : constant String := ".adt";
64
   Object_Suffix   : constant String := Get_Target_Object_Suffix.all;
65
   Debug_Suffix    : String          := ".dg";
66
   --  Changed to "_dg" for VMS in the body of the package
67
 
68
   Repinfo_Suffix  : String := ".rep";
69
   --  Changed to "_rep" for VMS in the body of the package
70
 
71
   B_Start : String_Ptr := new String'("b~");
72
   --  Prefix of binder generated file, and number of actual characters used.
73
   --  Changed to "b__" for VMS in the body of the package.
74
 
75
   Project_Tree : constant Project_Tree_Ref :=
76
                    new Project_Tree_Data (Is_Root_Tree => True);
77
   --  The project tree
78
 
79
   Object_Directory_Path : String_Access := null;
80
   --  The path name of the object directory, set with switch -D
81
 
82
   Force_Deletions : Boolean := False;
83
   --  Set to True by switch -f. When True, attempts to delete non writable
84
   --  files will be done.
85
 
86
   Do_Nothing : Boolean := False;
87
   --  Set to True when switch -n is specified. When True, no file is deleted.
88
   --  gnatclean only lists the files that would have been deleted if the
89
   --  switch -n had not been specified.
90
 
91
   File_Deleted : Boolean := False;
92
   --  Set to True if at least one file has been deleted
93
 
94
   Copyright_Displayed : Boolean := False;
95
   Usage_Displayed     : Boolean := False;
96
 
97
   Project_File_Name : String_Access := null;
98
 
99
   Project_Node_Tree : Project_Node_Tree_Ref;
100
 
101
   Root_Environment : Prj.Tree.Environment;
102
 
103
   Main_Project : Prj.Project_Id := Prj.No_Project;
104
 
105
   All_Projects : Boolean := False;
106
 
107
   --  Packages of project files where unknown attributes are errors
108
 
109
   Naming_String   : aliased String := "naming";
110
   Builder_String  : aliased String := "builder";
111
   Compiler_String : aliased String := "compiler";
112
   Binder_String   : aliased String := "binder";
113
   Linker_String   : aliased String := "linker";
114
 
115
   Gnatmake_Packages : aliased String_List :=
116
     (Naming_String   'Access,
117
      Builder_String  'Access,
118
      Compiler_String 'Access,
119
      Binder_String   'Access,
120
      Linker_String   'Access);
121
 
122
   Packages_To_Check_By_Gnatmake : constant String_List_Access :=
123
     Gnatmake_Packages'Access;
124
 
125
   package Processed_Projects is new Table.Table
126
     (Table_Component_Type => Project_Id,
127
      Table_Index_Type     => Natural,
128
      Table_Low_Bound      => 0,
129
      Table_Initial        => 10,
130
      Table_Increment      => 100,
131
      Table_Name           => "Clean.Processed_Projects");
132
   --  Table to keep track of what project files have been processed, when
133
   --  switch -r is specified.
134
 
135
   package Sources is new Table.Table
136
     (Table_Component_Type => File_Name_Type,
137
      Table_Index_Type     => Natural,
138
      Table_Low_Bound      => 0,
139
      Table_Initial        => 10,
140
      Table_Increment      => 100,
141
      Table_Name           => "Clean.Processed_Projects");
142
   --  Table to store all the source files of a library unit: spec, body and
143
   --  subunits, to detect .dg files and delete them.
144
 
145
   -----------------------------
146
   -- Other local subprograms --
147
   -----------------------------
148
 
149
   procedure Add_Source_Dir (N : String);
150
   --  Call Add_Src_Search_Dir and output one line when in verbose mode
151
 
152
   procedure Add_Source_Directories is
153
     new Prj.Env.For_All_Source_Dirs (Action => Add_Source_Dir);
154
 
155
   procedure Add_Object_Dir (N : String);
156
   --  Call Add_Lib_Search_Dir and output one line when in verbose mode
157
 
158
   procedure Add_Object_Directories is
159
     new Prj.Env.For_All_Object_Dirs (Action => Add_Object_Dir);
160
 
161
   function ALI_File_Name (Source : File_Name_Type) return String;
162
   --  Returns the name of the ALI file corresponding to Source
163
 
164
   function Assembly_File_Name (Source : File_Name_Type) return String;
165
   --  Returns the assembly file name corresponding to Source
166
 
167
   procedure Clean_Archive (Project : Project_Id; Global : Boolean);
168
   --  Delete a global archive or library project archive and the dependency
169
   --  file, if they exist.
170
 
171
   procedure Clean_Executables;
172
   --  Do the cleaning work when no project file is specified
173
 
174
   procedure Clean_Interface_Copy_Directory (Project : Project_Id);
175
   --  Delete files in an interface copy directory: any file that is a copy of
176
   --  a source of the project.
177
 
178
   procedure Clean_Library_Directory (Project : Project_Id);
179
   --  Delete the library file in a library directory and any ALI file of a
180
   --  source of the project in a library ALI directory.
181
 
182
   procedure Clean_Project (Project : Project_Id);
183
   --  Do the cleaning work when a project file is specified. This procedure
184
   --  calls itself recursively when there are several project files in the
185
   --  tree rooted at the main project file and switch -r has been specified.
186
 
187
   function Debug_File_Name (Source : File_Name_Type) return String;
188
   --  Name of the expanded source file corresponding to Source
189
 
190
   procedure Delete (In_Directory : String; File : String);
191
   --  Delete one file, or list the file name if switch -n is specified
192
 
193
   procedure Delete_Binder_Generated_Files
194
     (Dir    : String;
195
      Source : File_Name_Type);
196
   --  Delete the binder generated file in directory Dir for Source, if they
197
   --  exist: for Unix these are b~<source>.ads, b~<source>.adb,
198
   --  b~<source>.ali and b~<source>.o.
199
 
200
   procedure Display_Copyright;
201
   --  Display the Copyright notice. If called several times, display the
202
   --  Copyright notice only the first time.
203
 
204
   procedure Initialize;
205
   --  Call the necessary package initializations
206
 
207
   function Object_File_Name (Source : File_Name_Type) return String;
208
   --  Returns the object file name corresponding to Source
209
 
210
   procedure Parse_Cmd_Line;
211
   --  Parse the command line
212
 
213
   function Repinfo_File_Name (Source : File_Name_Type) return String;
214
   --  Returns the repinfo file name corresponding to Source
215
 
216
   function Tree_File_Name (Source : File_Name_Type) return String;
217
   --  Returns the tree file name corresponding to Source
218
 
219
   function In_Extension_Chain
220
     (Of_Project : Project_Id;
221
      Prj        : Project_Id) return Boolean;
222
   --  Returns True iff Prj is an extension of Of_Project or if Of_Project is
223
   --  an extension of Prj.
224
 
225
   procedure Usage;
226
   --  Display the usage. If called several times, the usage is displayed only
227
   --  the first time.
228
 
229
   --------------------
230
   -- Add_Object_Dir --
231
   --------------------
232
 
233
   procedure Add_Object_Dir (N : String) is
234
   begin
235
      Add_Lib_Search_Dir (N);
236
 
237
      if Opt.Verbose_Mode then
238
         Put ("Adding object directory """);
239
         Put (N);
240
         Put (""".");
241
         New_Line;
242
      end if;
243
   end Add_Object_Dir;
244
 
245
   --------------------
246
   -- Add_Source_Dir --
247
   --------------------
248
 
249
   procedure Add_Source_Dir (N : String) is
250
   begin
251
      Add_Src_Search_Dir (N);
252
 
253
      if Opt.Verbose_Mode then
254
         Put ("Adding source directory """);
255
         Put (N);
256
         Put (""".");
257
         New_Line;
258
      end if;
259
   end Add_Source_Dir;
260
 
261
   -------------------
262
   -- ALI_File_Name --
263
   -------------------
264
 
265
   function ALI_File_Name (Source : File_Name_Type) return String is
266
      Src : constant String := Get_Name_String (Source);
267
 
268
   begin
269
      --  If the source name has an extension, then replace it with
270
      --  the ALI suffix.
271
 
272
      for Index in reverse Src'First + 1 .. Src'Last loop
273
         if Src (Index) = '.' then
274
            return Src (Src'First .. Index - 1) & ALI_Suffix;
275
         end if;
276
      end loop;
277
 
278
      --  If there is no dot, or if it is the first character, just add the
279
      --  ALI suffix.
280
 
281
      return Src & ALI_Suffix;
282
   end ALI_File_Name;
283
 
284
   ------------------------
285
   -- Assembly_File_Name --
286
   ------------------------
287
 
288
   function Assembly_File_Name (Source : File_Name_Type) return String is
289
      Src : constant String := Get_Name_String (Source);
290
 
291
   begin
292
      --  If the source name has an extension, then replace it with
293
      --  the assembly suffix.
294
 
295
      for Index in reverse Src'First + 1 .. Src'Last loop
296
         if Src (Index) = '.' then
297
            return Src (Src'First .. Index - 1) & Assembly_Suffix;
298
         end if;
299
      end loop;
300
 
301
      --  If there is no dot, or if it is the first character, just add the
302
      --  assembly suffix.
303
 
304
      return Src & Assembly_Suffix;
305
   end Assembly_File_Name;
306
 
307
   -------------------
308
   -- Clean_Archive --
309
   -------------------
310
 
311
   procedure Clean_Archive (Project : Project_Id; Global : Boolean) is
312
      Current_Dir : constant Dir_Name_Str := Get_Current_Dir;
313
 
314
      Lib_Prefix : String_Access;
315
      Archive_Name : String_Access;
316
      --  The name of the archive file for this project
317
 
318
      Archive_Dep_Name : String_Access;
319
      --  The name of the archive dependency file for this project
320
 
321
      Obj_Dir : constant String :=
322
                  Get_Name_String (Project.Object_Directory.Display_Name);
323
 
324
   begin
325
      Change_Dir (Obj_Dir);
326
 
327
      --  First, get the lib prefix, the archive file name and the archive
328
      --  dependency file name.
329
 
330
      if Global then
331
         Lib_Prefix :=
332
           new String'("lib" & Get_Name_String (Project.Display_Name));
333
      else
334
         Lib_Prefix :=
335
           new String'("lib" & Get_Name_String (Project.Library_Name));
336
      end if;
337
 
338
      Archive_Name := new String'(Lib_Prefix.all & '.' & Archive_Ext);
339
      Archive_Dep_Name := new String'(Lib_Prefix.all & ".deps");
340
 
341
      --  Delete the archive file and the archive dependency file, if they
342
      --  exist.
343
 
344
      if Is_Regular_File (Archive_Name.all) then
345
         Delete (Obj_Dir, Archive_Name.all);
346
      end if;
347
 
348
      if Is_Regular_File (Archive_Dep_Name.all) then
349
         Delete (Obj_Dir, Archive_Dep_Name.all);
350
      end if;
351
 
352
      Change_Dir (Current_Dir);
353
   end Clean_Archive;
354
 
355
   -----------------------
356
   -- Clean_Executables --
357
   -----------------------
358
 
359
   procedure Clean_Executables is
360
      Main_Source_File : File_Name_Type;
361
      --  Current main source
362
 
363
      Main_Lib_File : File_Name_Type;
364
      --  ALI file of the current main
365
 
366
      Lib_File : File_Name_Type;
367
      --  Current ALI file
368
 
369
      Full_Lib_File : File_Name_Type;
370
      --  Full name of the current ALI file
371
 
372
      Text    : Text_Buffer_Ptr;
373
      The_ALI : ALI_Id;
374
      Found   : Boolean;
375
      Source  : Queue.Source_Info;
376
 
377
   begin
378
      Queue.Initialize (Queue_Per_Obj_Dir => False);
379
 
380
      --  It does not really matter if there is or not an object file
381
      --  corresponding to an ALI file: if there is one, it will be deleted.
382
 
383
      Opt.Check_Object_Consistency := False;
384
 
385
      --  Proceed each executable one by one. Each source is marked as it is
386
      --  processed, so common sources between executables will not be
387
      --  processed several times.
388
 
389
      for N_File in 1 .. Osint.Number_Of_Files loop
390
         Main_Source_File := Next_Main_Source;
391
         Main_Lib_File :=
392
           Osint.Lib_File_Name (Main_Source_File, Current_File_Index);
393
 
394
         if Main_Lib_File /= No_File then
395
            Queue.Insert
396
              ((Format  => Format_Gnatmake,
397
                File    => Main_Lib_File,
398
                Unit    => No_Unit_Name,
399
                Index   => 0,
400
                Project => No_Project));
401
         end if;
402
 
403
         while not Queue.Is_Empty loop
404
            Sources.Set_Last (0);
405
            Queue.Extract (Found, Source);
406
            pragma Assert (Found);
407
            pragma Assert (Source.File /= No_File);
408
            Lib_File := Source.File;
409
            Full_Lib_File := Osint.Full_Lib_File_Name (Lib_File);
410
 
411
            --  If we have existing ALI file that is not read-only, process it
412
 
413
            if Full_Lib_File /= No_File
414
              and then not Is_Readonly_Library (Full_Lib_File)
415
            then
416
               Text := Read_Library_Info (Lib_File);
417
 
418
               if Text /= null then
419
                  The_ALI :=
420
                    Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
421
                  Free (Text);
422
 
423
                  --  If no error was produced while loading this ALI file,
424
                  --  insert into the queue all the unmarked withed sources.
425
 
426
                  if The_ALI /= No_ALI_Id then
427
                     for J in ALIs.Table (The_ALI).First_Unit ..
428
                       ALIs.Table (The_ALI).Last_Unit
429
                     loop
430
                        Sources.Increment_Last;
431
                        Sources.Table (Sources.Last) :=
432
                          ALI.Units.Table (J).Sfile;
433
 
434
                        for K in ALI.Units.Table (J).First_With ..
435
                          ALI.Units.Table (J).Last_With
436
                        loop
437
                           if Withs.Table (K).Afile /= No_File then
438
                              Queue.Insert
439
                                ((Format  => Format_Gnatmake,
440
                                  File    => Withs.Table (K).Afile,
441
                                  Unit    => No_Unit_Name,
442
                                  Index   => 0,
443
                                  Project => No_Project));
444
                           end if;
445
                        end loop;
446
                     end loop;
447
 
448
                     --  Look for subunits and put them in the Sources table
449
 
450
                     for J in ALIs.Table (The_ALI).First_Sdep ..
451
                       ALIs.Table (The_ALI).Last_Sdep
452
                     loop
453
                        if Sdep.Table (J).Subunit_Name /= No_Name then
454
                           Sources.Increment_Last;
455
                           Sources.Table (Sources.Last) :=
456
                             Sdep.Table (J).Sfile;
457
                        end if;
458
                     end loop;
459
                  end if;
460
               end if;
461
 
462
               --  Now delete all existing files corresponding to this ALI file
463
 
464
               declare
465
                  Obj_Dir : constant String :=
466
                              Dir_Name (Get_Name_String (Full_Lib_File));
467
                  Obj     : constant String := Object_File_Name (Lib_File);
468
                  Adt     : constant String := Tree_File_Name   (Lib_File);
469
                  Asm     : constant String := Assembly_File_Name (Lib_File);
470
 
471
               begin
472
                  Delete (Obj_Dir, Get_Name_String (Lib_File));
473
 
474
                  if Is_Regular_File (Obj_Dir & Dir_Separator & Obj) then
475
                     Delete (Obj_Dir, Obj);
476
                  end if;
477
 
478
                  if Is_Regular_File (Obj_Dir & Dir_Separator & Adt) then
479
                     Delete (Obj_Dir, Adt);
480
                  end if;
481
 
482
                  if Is_Regular_File (Obj_Dir & Dir_Separator & Asm) then
483
                     Delete (Obj_Dir, Asm);
484
                  end if;
485
 
486
                  --  Delete expanded source files (.dg) and/or repinfo files
487
                  --  (.rep) if any
488
 
489
                  for J in 1 .. Sources.Last loop
490
                     declare
491
                        Deb : constant String :=
492
                                Debug_File_Name (Sources.Table (J));
493
                        Rep : constant String :=
494
                                Repinfo_File_Name (Sources.Table (J));
495
 
496
                     begin
497
                        if Is_Regular_File (Obj_Dir & Dir_Separator & Deb) then
498
                           Delete (Obj_Dir, Deb);
499
                        end if;
500
 
501
                        if Is_Regular_File (Obj_Dir & Dir_Separator & Rep) then
502
                           Delete (Obj_Dir, Rep);
503
                        end if;
504
                     end;
505
                  end loop;
506
               end;
507
            end if;
508
         end loop;
509
 
510
         --  Delete the executable, if it exists, and the binder generated
511
         --  files, if any.
512
 
513
         if not Compile_Only then
514
            declare
515
               Source     : constant File_Name_Type :=
516
                              Strip_Suffix (Main_Lib_File);
517
               Executable : constant String :=
518
                              Get_Name_String (Executable_Name (Source));
519
            begin
520
               if Is_Regular_File (Executable) then
521
                  Delete ("", Executable);
522
               end if;
523
 
524
               Delete_Binder_Generated_Files (Get_Current_Dir, Source);
525
            end;
526
         end if;
527
      end loop;
528
   end Clean_Executables;
529
 
530
   ------------------------------------
531
   -- Clean_Interface_Copy_Directory --
532
   ------------------------------------
533
 
534
   procedure Clean_Interface_Copy_Directory (Project : Project_Id) is
535
      Current : constant String := Get_Current_Dir;
536
 
537
      Direc : Dir_Type;
538
 
539
      Name : String (1 .. 200);
540
      Last : Natural;
541
 
542
      Delete_File : Boolean;
543
      Unit        : Unit_Index;
544
 
545
   begin
546
      if Project.Library
547
        and then Project.Library_Src_Dir /= No_Path_Information
548
      then
549
         declare
550
            Directory : constant String :=
551
                        Get_Name_String (Project.Library_Src_Dir.Display_Name);
552
 
553
         begin
554
            Change_Dir (Directory);
555
            Open (Direc, ".");
556
 
557
            --  For each regular file in the directory, if switch -n has not
558
            --  been specified, make it writable and delete the file if it is
559
            --  a copy of a source of the project.
560
 
561
            loop
562
               Read (Direc, Name, Last);
563
               exit when Last = 0;
564
 
565
               declare
566
                  Filename : constant String := Name (1 .. Last);
567
 
568
               begin
569
                  if Is_Regular_File (Filename) then
570
                     Canonical_Case_File_Name (Name (1 .. Last));
571
                     Delete_File := False;
572
 
573
                     Unit := Units_Htable.Get_First (Project_Tree.Units_HT);
574
 
575
                     --  Compare with source file names of the project
576
 
577
                     while Unit /= No_Unit_Index loop
578
                        if Unit.File_Names (Impl) /= null
579
                          and then Ultimate_Extending_Project_Of
580
                                     (Unit.File_Names (Impl).Project) = Project
581
                          and then
582
                            Get_Name_String (Unit.File_Names (Impl).File) =
583
                                                              Name (1 .. Last)
584
                        then
585
                           Delete_File := True;
586
                           exit;
587
                        end if;
588
 
589
                        if Unit.File_Names (Spec) /= null
590
                          and then Ultimate_Extending_Project_Of
591
                                     (Unit.File_Names (Spec).Project) = Project
592
                          and then
593
                            Get_Name_String
594
                              (Unit.File_Names (Spec).File) = Name (1 .. Last)
595
                        then
596
                           Delete_File := True;
597
                           exit;
598
                        end if;
599
 
600
                        Unit := Units_Htable.Get_Next (Project_Tree.Units_HT);
601
                     end loop;
602
 
603
                     if Delete_File then
604
                        if not Do_Nothing then
605
                           Set_Writable (Filename);
606
                        end if;
607
 
608
                        Delete (Directory, Filename);
609
                     end if;
610
                  end if;
611
               end;
612
            end loop;
613
 
614
            Close (Direc);
615
 
616
            --  Restore the initial working directory
617
 
618
            Change_Dir (Current);
619
         end;
620
      end if;
621
   end Clean_Interface_Copy_Directory;
622
 
623
   -----------------------------
624
   -- Clean_Library_Directory --
625
   -----------------------------
626
 
627
   Empty_String : aliased String := "";
628
 
629
   procedure Clean_Library_Directory (Project : Project_Id) is
630
      Current : constant String := Get_Current_Dir;
631
 
632
      Lib_Filename : constant String := Get_Name_String (Project.Library_Name);
633
      DLL_Name     : String :=
634
                       DLL_Prefix & Lib_Filename & "." & DLL_Ext;
635
      Archive_Name : String :=
636
                       "lib" & Lib_Filename & "." & Archive_Ext;
637
      Direc        : Dir_Type;
638
 
639
      Name : String (1 .. 200);
640
      Last : Natural;
641
 
642
      Delete_File : Boolean;
643
 
644
      Minor : String_Access := Empty_String'Access;
645
      Major : String_Access := Empty_String'Access;
646
 
647
   begin
648
      if Project.Library then
649
         if Project.Library_Kind /= Static
650
           and then MLib.Tgt.Library_Major_Minor_Id_Supported
651
           and then Project.Lib_Internal_Name /= No_Name
652
         then
653
            Minor := new String'(Get_Name_String (Project.Lib_Internal_Name));
654
            Major := new String'(MLib.Major_Id_Name (DLL_Name, Minor.all));
655
         end if;
656
 
657
         declare
658
            Lib_Directory     : constant String :=
659
                                  Get_Name_String
660
                                    (Project.Library_Dir.Display_Name);
661
            Lib_ALI_Directory : constant String :=
662
                                  Get_Name_String
663
                                    (Project.Library_ALI_Dir.Display_Name);
664
 
665
         begin
666
            Canonical_Case_File_Name (Archive_Name);
667
            Canonical_Case_File_Name (DLL_Name);
668
 
669
            Change_Dir (Lib_Directory);
670
            Open (Direc, ".");
671
 
672
            --  For each regular file in the directory, if switch -n has not
673
            --  been specified, make it writable and delete the file if it is
674
            --  the library file.
675
 
676
            loop
677
               Read (Direc, Name, Last);
678
               exit when Last = 0;
679
 
680
               declare
681
                  Filename : constant String := Name (1 .. Last);
682
 
683
               begin
684
                  if Is_Regular_File (Filename)
685
                    or else Is_Symbolic_Link (Filename)
686
                  then
687
                     Canonical_Case_File_Name (Name (1 .. Last));
688
                     Delete_File := False;
689
 
690
                     if (Project.Library_Kind = Static
691
                          and then Name (1 .. Last) =  Archive_Name)
692
                       or else
693
                         ((Project.Library_Kind = Dynamic
694
                             or else
695
                           Project.Library_Kind = Relocatable)
696
                          and then
697
                            (Name (1 .. Last) = DLL_Name
698
                               or else
699
                             Name (1 .. Last) = Minor.all
700
                               or else
701
                             Name (1 .. Last) = Major.all))
702
                     then
703
                        if not Do_Nothing then
704
                           Set_Writable (Filename);
705
                        end if;
706
 
707
                        Delete (Lib_Directory, Filename);
708
                     end if;
709
                  end if;
710
               end;
711
            end loop;
712
 
713
            Close (Direc);
714
 
715
            Change_Dir (Lib_ALI_Directory);
716
            Open (Direc, ".");
717
 
718
            --  For each regular file in the directory, if switch -n has not
719
            --  been specified, make it writable and delete the file if it is
720
            --  any ALI file of a source of the project.
721
 
722
            loop
723
               Read (Direc, Name, Last);
724
               exit when Last = 0;
725
 
726
               declare
727
                  Filename : constant String := Name (1 .. Last);
728
               begin
729
                  if Is_Regular_File (Filename) then
730
                     Canonical_Case_File_Name (Name (1 .. Last));
731
                     Delete_File := False;
732
 
733
                     if Last > 4 and then Name (Last - 3 .. Last) = ".ali" then
734
                        declare
735
                           Unit : Unit_Index;
736
                        begin
737
                           --  Compare with ALI file names of the project
738
 
739
                           Unit := Units_Htable.Get_First
740
                             (Project_Tree.Units_HT);
741
                           while Unit /= No_Unit_Index loop
742
                              if Unit.File_Names (Impl) /= null
743
                                and then Unit.File_Names (Impl).Project /=
744
                                                                   No_Project
745
                              then
746
                                 if Ultimate_Extending_Project_Of
747
                                      (Unit.File_Names (Impl).Project) =
748
                                                                   Project
749
                                 then
750
                                    Get_Name_String
751
                                      (Unit.File_Names (Impl).File);
752
                                    Name_Len := Name_Len -
753
                                      File_Extension
754
                                        (Name (1 .. Name_Len))'Length;
755
                                    if Name_Buffer (1 .. Name_Len) =
756
                                         Name (1 .. Last - 4)
757
                                    then
758
                                       Delete_File := True;
759
                                       exit;
760
                                    end if;
761
                                 end if;
762
 
763
                              elsif Unit.File_Names (Spec) /= null
764
                                and then Ultimate_Extending_Project_Of
765
                                           (Unit.File_Names (Spec).Project) =
766
                                                                    Project
767
                              then
768
                                 Get_Name_String
769
                                   (Unit.File_Names (Spec).File);
770
                                 Name_Len :=
771
                                   Name_Len -
772
                                     File_Extension
773
                                       (Name (1 .. Name_Len))'Length;
774
 
775
                                 if Name_Buffer (1 .. Name_Len) =
776
                                      Name (1 .. Last - 4)
777
                                 then
778
                                    Delete_File := True;
779
                                    exit;
780
                                 end if;
781
                              end if;
782
 
783
                              Unit :=
784
                                Units_Htable.Get_Next (Project_Tree.Units_HT);
785
                           end loop;
786
                        end;
787
                     end if;
788
 
789
                     if Delete_File then
790
                        if not Do_Nothing then
791
                           Set_Writable (Filename);
792
                        end if;
793
 
794
                        Delete (Lib_ALI_Directory, Filename);
795
                     end if;
796
                  end if;
797
               end;
798
            end loop;
799
 
800
            Close (Direc);
801
 
802
            --  Restore the initial working directory
803
 
804
            Change_Dir (Current);
805
         end;
806
      end if;
807
   end Clean_Library_Directory;
808
 
809
   -------------------
810
   -- Clean_Project --
811
   -------------------
812
 
813
   procedure Clean_Project (Project : Project_Id) is
814
      Main_Source_File : File_Name_Type;
815
      --  Name of executable on the command line without directory info
816
 
817
      Executable : File_Name_Type;
818
      --  Name of the executable file
819
 
820
      Current_Dir : constant Dir_Name_Str := Get_Current_Dir;
821
      Unit        : Unit_Index;
822
      File_Name1  : File_Name_Type;
823
      Index1      : Int;
824
      File_Name2  : File_Name_Type;
825
      Index2      : Int;
826
      Lib_File    : File_Name_Type;
827
 
828
      Global_Archive : Boolean := False;
829
 
830
   begin
831
      --  Check that we don't specify executable on the command line for
832
      --  a main library project.
833
 
834
      if Project = Main_Project
835
        and then Osint.Number_Of_Files /= 0
836
        and then Project.Library
837
      then
838
         Osint.Fail
839
           ("Cannot specify executable(s) for a Library Project File");
840
      end if;
841
 
842
      --  Nothing to clean in an externally built project
843
 
844
      if Project.Externally_Built then
845
         if Verbose_Mode then
846
            Put ("Nothing to do to clean externally built project """);
847
            Put (Get_Name_String (Project.Name));
848
            Put_Line ("""");
849
         end if;
850
 
851
      else
852
         if Verbose_Mode then
853
            Put ("Cleaning project """);
854
            Put (Get_Name_String (Project.Name));
855
            Put_Line ("""");
856
         end if;
857
 
858
         --  Add project to the list of processed projects
859
 
860
         Processed_Projects.Increment_Last;
861
         Processed_Projects.Table (Processed_Projects.Last) := Project;
862
 
863
         if Project.Object_Directory /= No_Path_Information then
864
            declare
865
               Obj_Dir : constant String :=
866
                           Get_Name_String
867
                             (Project.Object_Directory.Display_Name);
868
 
869
            begin
870
               Change_Dir (Obj_Dir);
871
 
872
               --  First, deal with Ada
873
 
874
               --  Look through the units to find those that are either
875
               --  immediate sources or inherited sources of the project.
876
               --  Extending projects may have no language specified, if
877
               --  Source_Dirs or Source_Files is specified as an empty list,
878
               --  so always look for Ada units in extending projects.
879
 
880
               if Has_Ada_Sources (Project)
881
                 or else Project.Extends /= No_Project
882
               then
883
                  Unit := Units_Htable.Get_First (Project_Tree.Units_HT);
884
                  while Unit /= No_Unit_Index loop
885
                     File_Name1 := No_File;
886
                     File_Name2 := No_File;
887
 
888
                     --  If either the spec or the body is a source of the
889
                     --  project, check for the corresponding ALI file in the
890
                     --  object directory.
891
 
892
                     if (Unit.File_Names (Impl) /= null
893
                         and then
894
                           In_Extension_Chain
895
                             (Unit.File_Names (Impl).Project, Project))
896
                       or else
897
                         (Unit.File_Names (Spec) /= null
898
                          and then In_Extension_Chain
899
                            (Unit.File_Names (Spec).Project, Project))
900
                     then
901
                        if Unit.File_Names (Impl) /= null then
902
                           File_Name1 := Unit.File_Names (Impl).File;
903
                           Index1     := Unit.File_Names (Impl).Index;
904
                        else
905
                           File_Name1 := No_File;
906
                           Index1     := 0;
907
                        end if;
908
 
909
                        if Unit.File_Names (Spec) /= null then
910
                           File_Name2 := Unit.File_Names (Spec).File;
911
                           Index2     := Unit.File_Names (Spec).Index;
912
                        else
913
                           File_Name2 := No_File;
914
                           Index2     := 0;
915
                        end if;
916
 
917
                        --  If there is no body file name, then there may be
918
                        --  only a spec.
919
 
920
                        if File_Name1 = No_File then
921
                           File_Name1 := File_Name2;
922
                           Index1     := Index2;
923
                           File_Name2 := No_File;
924
                           Index2     := 0;
925
                        end if;
926
                     end if;
927
 
928
                     --  If there is either a spec or a body, look for files
929
                     --  in the object directory.
930
 
931
                     if File_Name1 /= No_File then
932
                        Lib_File := Osint.Lib_File_Name (File_Name1, Index1);
933
 
934
                        declare
935
                           Asm : constant String :=
936
                                   Assembly_File_Name (Lib_File);
937
                           ALI : constant String :=
938
                                   ALI_File_Name      (Lib_File);
939
                           Obj : constant String :=
940
                                   Object_File_Name   (Lib_File);
941
                           Adt : constant String :=
942
                                   Tree_File_Name     (Lib_File);
943
                           Deb : constant String :=
944
                                   Debug_File_Name    (File_Name1);
945
                           Rep : constant String :=
946
                                   Repinfo_File_Name  (File_Name1);
947
                           Del : Boolean := True;
948
 
949
                        begin
950
                           --  If the ALI file exists and is read-only, no file
951
                           --  is deleted.
952
 
953
                           if Is_Regular_File (ALI) then
954
                              if Is_Writable_File (ALI) then
955
                                 Delete (Obj_Dir, ALI);
956
 
957
                              else
958
                                 Del := False;
959
 
960
                                 if Verbose_Mode then
961
                                    Put ('"');
962
                                    Put (Obj_Dir);
963
 
964
                                    if Obj_Dir (Obj_Dir'Last) /=
965
                                      Dir_Separator
966
                                    then
967
                                       Put (Dir_Separator);
968
                                    end if;
969
 
970
                                    Put (ALI);
971
                                    Put_Line (""" is read-only");
972
                                 end if;
973
                              end if;
974
                           end if;
975
 
976
                           if Del then
977
 
978
                              --  Object file
979
 
980
                              if Is_Regular_File (Obj) then
981
                                 Delete (Obj_Dir, Obj);
982
                              end if;
983
 
984
                              --  Assembly file
985
 
986
                              if Is_Regular_File (Asm) then
987
                                 Delete (Obj_Dir, Asm);
988
                              end if;
989
 
990
                              --  Tree file
991
 
992
                              if Is_Regular_File (Adt) then
993
                                 Delete (Obj_Dir, Adt);
994
                              end if;
995
 
996
                              --  First expanded source file
997
 
998
                              if Is_Regular_File (Deb) then
999
                                 Delete (Obj_Dir, Deb);
1000
                              end if;
1001
 
1002
                              --  Repinfo file
1003
 
1004
                              if Is_Regular_File (Rep) then
1005
                                 Delete (Obj_Dir, Rep);
1006
                              end if;
1007
 
1008
                              --  Second expanded source file
1009
 
1010
                              if File_Name2 /= No_File then
1011
                                 declare
1012
                                    Deb : constant String :=
1013
                                            Debug_File_Name (File_Name2);
1014
                                    Rep : constant String :=
1015
                                            Repinfo_File_Name (File_Name2);
1016
 
1017
                                 begin
1018
                                    if Is_Regular_File (Deb) then
1019
                                       Delete (Obj_Dir, Deb);
1020
                                    end if;
1021
 
1022
                                    if Is_Regular_File (Rep) then
1023
                                       Delete (Obj_Dir, Rep);
1024
                                    end if;
1025
                                 end;
1026
                              end if;
1027
                           end if;
1028
                        end;
1029
                     end if;
1030
 
1031
                     Unit := Units_Htable.Get_Next (Project_Tree.Units_HT);
1032
                  end loop;
1033
               end if;
1034
 
1035
               --  Check if a global archive and it dependency file could have
1036
               --  been created and, if they exist, delete them.
1037
 
1038
               if Project = Main_Project and then not Project.Library then
1039
                  Global_Archive := False;
1040
 
1041
                  declare
1042
                     Proj : Project_List;
1043
 
1044
                  begin
1045
                     Proj := Project_Tree.Projects;
1046
                     while Proj /= null loop
1047
 
1048
                        --  For gnatmake, when the project specifies more than
1049
                        --  just Ada as a language (even if course we could not
1050
                        --  find any source file for the other languages), we
1051
                        --  will take all the object files found in the object
1052
                        --  directories. Since we know the project supports at
1053
                        --  least Ada, we just have to test whether it has at
1054
                        --  least two languages, and we do not care about the
1055
                        --  sources.
1056
 
1057
                        if Proj.Project.Languages /= null
1058
                          and then Proj.Project.Languages.Next /= null
1059
                        then
1060
                           Global_Archive := True;
1061
                           exit;
1062
                        end if;
1063
 
1064
                        Proj := Proj.Next;
1065
                     end loop;
1066
                  end;
1067
 
1068
                  if Global_Archive then
1069
                     Clean_Archive (Project, Global => True);
1070
                  end if;
1071
               end if;
1072
 
1073
            end;
1074
         end if;
1075
 
1076
         --  If this is a library project, clean the library directory, the
1077
         --  interface copy dir and, for a Stand-Alone Library, the binder
1078
         --  generated files of the library.
1079
 
1080
         --  The directories are cleaned only if switch -c is not specified
1081
 
1082
         if Project.Library then
1083
            if not Compile_Only then
1084
               Clean_Library_Directory (Project);
1085
 
1086
               if Project.Library_Src_Dir /= No_Path_Information then
1087
                  Clean_Interface_Copy_Directory (Project);
1088
               end if;
1089
            end if;
1090
 
1091
            if Project.Standalone_Library /= No
1092
              and then Project.Object_Directory /= No_Path_Information
1093
            then
1094
               Delete_Binder_Generated_Files
1095
                 (Get_Name_String (Project.Object_Directory.Display_Name),
1096
                  File_Name_Type (Project.Library_Name));
1097
            end if;
1098
         end if;
1099
 
1100
         if Verbose_Mode then
1101
            New_Line;
1102
         end if;
1103
      end if;
1104
 
1105
      --  If switch -r is specified, call Clean_Project recursively for the
1106
      --  imported projects and the project being extended.
1107
 
1108
      if All_Projects then
1109
         declare
1110
            Imported : Project_List;
1111
            Process  : Boolean;
1112
 
1113
         begin
1114
            --  For each imported project, call Clean_Project if the project
1115
            --  has not been processed already.
1116
 
1117
            Imported := Project.Imported_Projects;
1118
            while Imported /= null loop
1119
               Process := True;
1120
 
1121
               for
1122
                 J in Processed_Projects.First .. Processed_Projects.Last
1123
               loop
1124
                  if Imported.Project = Processed_Projects.Table (J) then
1125
                     Process := False;
1126
                     exit;
1127
                  end if;
1128
               end loop;
1129
 
1130
               if Process then
1131
                  Clean_Project (Imported.Project);
1132
               end if;
1133
 
1134
               Imported := Imported.Next;
1135
            end loop;
1136
 
1137
            --  If this project extends another project, call Clean_Project for
1138
            --  the project being extended. It is guaranteed that it has not
1139
            --  called before, because no other project may import or extend
1140
            --  this project.
1141
 
1142
            if Project.Extends /= No_Project then
1143
               Clean_Project (Project.Extends);
1144
            end if;
1145
         end;
1146
      end if;
1147
 
1148
         --  For the main project, delete the executables and the binder
1149
         --  generated files.
1150
 
1151
         --  The executables are deleted only if switch -c is not specified
1152
 
1153
      if Project = Main_Project
1154
        and then Project.Exec_Directory /= No_Path_Information
1155
      then
1156
         declare
1157
            Exec_Dir : constant String :=
1158
                         Get_Name_String (Project.Exec_Directory.Display_Name);
1159
 
1160
         begin
1161
            Change_Dir (Exec_Dir);
1162
 
1163
            for N_File in 1 .. Osint.Number_Of_Files loop
1164
               Main_Source_File := Next_Main_Source;
1165
 
1166
               if not Compile_Only then
1167
                  Executable :=
1168
                    Executable_Of
1169
                      (Main_Project,
1170
                       Project_Tree.Shared,
1171
                       Main_Source_File,
1172
                       Current_File_Index);
1173
 
1174
                  declare
1175
                     Exec_File_Name : constant String :=
1176
                                        Get_Name_String (Executable);
1177
 
1178
                  begin
1179
                     if Is_Absolute_Path (Name => Exec_File_Name) then
1180
                        if Is_Regular_File (Exec_File_Name) then
1181
                           Delete ("", Exec_File_Name);
1182
                        end if;
1183
 
1184
                     else
1185
                        if Is_Regular_File (Exec_File_Name) then
1186
                           Delete (Exec_Dir, Exec_File_Name);
1187
                        end if;
1188
                     end if;
1189
                  end;
1190
               end if;
1191
 
1192
               if Project.Object_Directory /= No_Path_Information then
1193
                  Delete_Binder_Generated_Files
1194
                    (Get_Name_String (Project.Object_Directory.Display_Name),
1195
                     Strip_Suffix (Main_Source_File));
1196
               end if;
1197
            end loop;
1198
         end;
1199
      end if;
1200
 
1201
      --  Change back to previous directory
1202
 
1203
      Change_Dir (Current_Dir);
1204
   end Clean_Project;
1205
 
1206
   ---------------------
1207
   -- Debug_File_Name --
1208
   ---------------------
1209
 
1210
   function Debug_File_Name (Source : File_Name_Type) return String is
1211
   begin
1212
      return Get_Name_String (Source) & Debug_Suffix;
1213
   end Debug_File_Name;
1214
 
1215
   ------------
1216
   -- Delete --
1217
   ------------
1218
 
1219
   procedure Delete (In_Directory : String; File : String) is
1220
      Full_Name : String (1 .. In_Directory'Length + File'Length + 1);
1221
      Last      : Natural := 0;
1222
      Success   : Boolean;
1223
 
1224
   begin
1225
      --  Indicate that at least one file is deleted or is to be deleted
1226
 
1227
      File_Deleted := True;
1228
 
1229
      --  Build the path name of the file to delete
1230
 
1231
      Last := In_Directory'Length;
1232
      Full_Name (1 .. Last) := In_Directory;
1233
 
1234
      if Last > 0 and then Full_Name (Last) /= Directory_Separator then
1235
         Last := Last + 1;
1236
         Full_Name (Last) := Directory_Separator;
1237
      end if;
1238
 
1239
      Full_Name (Last + 1 .. Last + File'Length) := File;
1240
      Last := Last + File'Length;
1241
 
1242
      --  If switch -n was used, simply output the path name
1243
 
1244
      if Do_Nothing then
1245
         Put_Line (Full_Name (1 .. Last));
1246
 
1247
      --  Otherwise, delete the file if it is writable
1248
 
1249
      else
1250
         if Force_Deletions
1251
           or else Is_Writable_File (Full_Name (1 .. Last))
1252
           or else Is_Symbolic_Link (Full_Name (1 .. Last))
1253
         then
1254
            Delete_File (Full_Name (1 .. Last), Success);
1255
         else
1256
            Success := False;
1257
         end if;
1258
 
1259
         if Verbose_Mode or else not Quiet_Output then
1260
            if not Success then
1261
               Put ("Warning: """);
1262
               Put (Full_Name (1 .. Last));
1263
               Put_Line (""" could not be deleted");
1264
 
1265
            else
1266
               Put ("""");
1267
               Put (Full_Name (1 .. Last));
1268
               Put_Line (""" has been deleted");
1269
            end if;
1270
         end if;
1271
      end if;
1272
   end Delete;
1273
 
1274
   -----------------------------------
1275
   -- Delete_Binder_Generated_Files --
1276
   -----------------------------------
1277
 
1278
   procedure Delete_Binder_Generated_Files
1279
     (Dir    : String;
1280
      Source : File_Name_Type)
1281
   is
1282
      Source_Name : constant String   := Get_Name_String (Source);
1283
      Current     : constant String   := Get_Current_Dir;
1284
      Last        : constant Positive := B_Start'Length + Source_Name'Length;
1285
      File_Name   : String (1 .. Last + 4);
1286
 
1287
   begin
1288
      Change_Dir (Dir);
1289
 
1290
      --  Build the file name (before the extension)
1291
 
1292
      File_Name (1 .. B_Start'Length) := B_Start.all;
1293
      File_Name (B_Start'Length + 1 .. Last) := Source_Name;
1294
 
1295
      --  Spec
1296
 
1297
      File_Name (Last + 1 .. Last + 4) := ".ads";
1298
 
1299
      if Is_Regular_File (File_Name (1 .. Last + 4)) then
1300
         Delete (Dir, File_Name (1 .. Last + 4));
1301
      end if;
1302
 
1303
      --  Body
1304
 
1305
      File_Name (Last + 1 .. Last + 4) := ".adb";
1306
 
1307
      if Is_Regular_File (File_Name (1 .. Last + 4)) then
1308
         Delete (Dir, File_Name (1 .. Last + 4));
1309
      end if;
1310
 
1311
      --  ALI file
1312
 
1313
      File_Name (Last + 1 .. Last + 4) := ".ali";
1314
 
1315
      if Is_Regular_File (File_Name (1 .. Last + 4)) then
1316
         Delete (Dir, File_Name (1 .. Last + 4));
1317
      end if;
1318
 
1319
      --  Object file
1320
 
1321
      File_Name (Last + 1 .. Last + Object_Suffix'Length) := Object_Suffix;
1322
 
1323
      if Is_Regular_File (File_Name (1 .. Last + Object_Suffix'Length)) then
1324
         Delete (Dir, File_Name (1 .. Last + Object_Suffix'Length));
1325
      end if;
1326
 
1327
      --  Change back to previous directory
1328
 
1329
      Change_Dir (Current);
1330
   end Delete_Binder_Generated_Files;
1331
 
1332
   -----------------------
1333
   -- Display_Copyright --
1334
   -----------------------
1335
 
1336
   procedure Display_Copyright is
1337
   begin
1338
      if not Copyright_Displayed then
1339
         Copyright_Displayed := True;
1340
         Display_Version ("GNATCLEAN", "2003");
1341
      end if;
1342
   end Display_Copyright;
1343
 
1344
   ---------------
1345
   -- Gnatclean --
1346
   ---------------
1347
 
1348
   procedure Gnatclean is
1349
   begin
1350
      --  Do the necessary initializations
1351
 
1352
      Clean.Initialize;
1353
 
1354
      --  Parse the command line, getting the switches and the executable names
1355
 
1356
      Parse_Cmd_Line;
1357
 
1358
      if Verbose_Mode then
1359
         Display_Copyright;
1360
      end if;
1361
 
1362
      if Project_File_Name /= null then
1363
 
1364
         --  A project file was specified by a -P switch
1365
 
1366
         if Opt.Verbose_Mode then
1367
            New_Line;
1368
            Put ("Parsing Project File """);
1369
            Put (Project_File_Name.all);
1370
            Put_Line (""".");
1371
            New_Line;
1372
         end if;
1373
 
1374
         --  Set the project parsing verbosity to whatever was specified
1375
         --  by a possible -vP switch.
1376
 
1377
         Prj.Pars.Set_Verbosity (To => Current_Verbosity);
1378
 
1379
         --  Parse the project file. If there is an error, Main_Project
1380
         --  will still be No_Project.
1381
 
1382
         Prj.Pars.Parse
1383
           (Project           => Main_Project,
1384
            In_Tree           => Project_Tree,
1385
            In_Node_Tree      => Project_Node_Tree,
1386
            Project_File_Name => Project_File_Name.all,
1387
            Env               => Root_Environment,
1388
            Packages_To_Check => Packages_To_Check_By_Gnatmake);
1389
 
1390
         if Main_Project = No_Project then
1391
            Fail ("""" & Project_File_Name.all & """ processing failed");
1392
         end if;
1393
 
1394
         if Opt.Verbose_Mode then
1395
            New_Line;
1396
            Put ("Parsing of Project File """);
1397
            Put (Project_File_Name.all);
1398
            Put (""" is finished.");
1399
            New_Line;
1400
         end if;
1401
 
1402
         --  Add source directories and object directories to the search paths
1403
 
1404
         Add_Source_Directories (Main_Project, Project_Tree);
1405
         Add_Object_Directories (Main_Project, Project_Tree);
1406
      end if;
1407
 
1408
      Osint.Add_Default_Search_Dirs;
1409
 
1410
      --  If a project file was specified, but no executable name, put all
1411
      --  the mains of the project file (if any) as if there were on the
1412
      --  command line.
1413
 
1414
      if Main_Project /= No_Project and then Osint.Number_Of_Files = 0 then
1415
         declare
1416
            Main  : String_Element;
1417
            Value : String_List_Id := Main_Project.Mains;
1418
         begin
1419
            while Value /= Prj.Nil_String loop
1420
               Main := Project_Tree.Shared.String_Elements.Table (Value);
1421
               Osint.Add_File
1422
                 (File_Name => Get_Name_String (Main.Value),
1423
                  Index     => Main.Index);
1424
               Value := Main.Next;
1425
            end loop;
1426
         end;
1427
      end if;
1428
 
1429
      --  If neither a project file nor an executable were specified, output
1430
      --  the usage and exit.
1431
 
1432
      if Main_Project = No_Project and then Osint.Number_Of_Files = 0 then
1433
         Usage;
1434
         return;
1435
      end if;
1436
 
1437
      if Verbose_Mode then
1438
         New_Line;
1439
      end if;
1440
 
1441
      if Main_Project /= No_Project then
1442
 
1443
         --  If a project file has been specified, call Clean_Project with the
1444
         --  project id of this project file, after resetting the list of
1445
         --  processed projects.
1446
 
1447
         Processed_Projects.Init;
1448
         Clean_Project (Main_Project);
1449
 
1450
      else
1451
         --  If no project file has been specified, the work is done in
1452
         --  Clean_Executables.
1453
 
1454
         Clean_Executables;
1455
      end if;
1456
 
1457
      --  In verbose mode, if Delete has not been called, indicate that no file
1458
      --  needs to be deleted.
1459
 
1460
      if Verbose_Mode and (not File_Deleted) then
1461
         New_Line;
1462
 
1463
         if Do_Nothing then
1464
            Put_Line ("No file needs to be deleted");
1465
         else
1466
            Put_Line ("No file has been deleted");
1467
         end if;
1468
      end if;
1469
   end Gnatclean;
1470
 
1471
   ------------------------
1472
   -- In_Extension_Chain --
1473
   ------------------------
1474
 
1475
   function In_Extension_Chain
1476
     (Of_Project : Project_Id;
1477
      Prj        : Project_Id) return Boolean
1478
   is
1479
      Proj : Project_Id;
1480
 
1481
   begin
1482
      if Prj = No_Project or else Of_Project = No_Project then
1483
         return False;
1484
      end if;
1485
 
1486
      if Of_Project = Prj then
1487
         return True;
1488
      end if;
1489
 
1490
      Proj := Of_Project;
1491
      while Proj.Extends /= No_Project loop
1492
         if Proj.Extends = Prj then
1493
            return True;
1494
         end if;
1495
 
1496
         Proj := Proj.Extends;
1497
      end loop;
1498
 
1499
      Proj := Prj;
1500
      while Proj.Extends /= No_Project loop
1501
         if Proj.Extends = Of_Project then
1502
            return True;
1503
         end if;
1504
 
1505
         Proj := Proj.Extends;
1506
      end loop;
1507
 
1508
      return False;
1509
   end In_Extension_Chain;
1510
 
1511
   ----------------
1512
   -- Initialize --
1513
   ----------------
1514
 
1515
   procedure Initialize is
1516
   begin
1517
      if not Initialized then
1518
         Initialized := True;
1519
 
1520
         --  Get default search directories to locate system.ads when calling
1521
         --  Targparm.Get_Target_Parameters.
1522
 
1523
         Osint.Add_Default_Search_Dirs;
1524
 
1525
         --  Initialize some packages
1526
 
1527
         Csets.Initialize;
1528
         Snames.Initialize;
1529
 
1530
         Prj.Tree.Initialize (Root_Environment, Gnatmake_Flags);
1531
         Prj.Env.Initialize_Default_Project_Path
1532
            (Root_Environment.Project_Path,
1533
             Target_Name => Sdefault.Target_Name.all);
1534
 
1535
         Project_Node_Tree := new Project_Node_Tree_Data;
1536
         Prj.Tree.Initialize (Project_Node_Tree);
1537
 
1538
         Prj.Initialize (Project_Tree);
1539
 
1540
         --  Check if the platform is VMS and, if it is, change some variables
1541
 
1542
         Targparm.Get_Target_Parameters;
1543
 
1544
         if OpenVMS_On_Target then
1545
            Debug_Suffix (Debug_Suffix'First) := '_';
1546
            Repinfo_Suffix (Repinfo_Suffix'First) := '_';
1547
            B_Start := new String'("b__");
1548
         end if;
1549
      end if;
1550
 
1551
      --  Reset global variables
1552
 
1553
      Free (Object_Directory_Path);
1554
      Do_Nothing := False;
1555
      File_Deleted := False;
1556
      Copyright_Displayed := False;
1557
      Usage_Displayed := False;
1558
      Free (Project_File_Name);
1559
      Main_Project := Prj.No_Project;
1560
      All_Projects := False;
1561
   end Initialize;
1562
 
1563
   ----------------------
1564
   -- Object_File_Name --
1565
   ----------------------
1566
 
1567
   function Object_File_Name (Source : File_Name_Type) return String is
1568
      Src : constant String := Get_Name_String (Source);
1569
 
1570
   begin
1571
      --  If the source name has an extension, then replace it with
1572
      --  the Object suffix.
1573
 
1574
      for Index in reverse Src'First + 1 .. Src'Last loop
1575
         if Src (Index) = '.' then
1576
            return Src (Src'First .. Index - 1) & Object_Suffix;
1577
         end if;
1578
      end loop;
1579
 
1580
      --  If there is no dot, or if it is the first character, just add the
1581
      --  ALI suffix.
1582
 
1583
      return Src & Object_Suffix;
1584
   end Object_File_Name;
1585
 
1586
   --------------------
1587
   -- Parse_Cmd_Line --
1588
   --------------------
1589
 
1590
   procedure Parse_Cmd_Line is
1591
      Last         : constant Natural := Argument_Count;
1592
      Source_Index : Int := 0;
1593
      Index        : Positive;
1594
 
1595
      procedure Check_Version_And_Help is new Check_Version_And_Help_G (Usage);
1596
 
1597
   begin
1598
      --  First, check for --version and --help
1599
 
1600
      Check_Version_And_Help ("GNATCLEAN", "2003");
1601
 
1602
      Index := 1;
1603
      while Index <= Last loop
1604
         declare
1605
            Arg : constant String := Argument (Index);
1606
 
1607
            procedure Bad_Argument;
1608
            --  Signal bad argument
1609
 
1610
            ------------------
1611
            -- Bad_Argument --
1612
            ------------------
1613
 
1614
            procedure Bad_Argument is
1615
            begin
1616
               Fail ("invalid argument """ & Arg & """");
1617
            end Bad_Argument;
1618
 
1619
         begin
1620
            if Arg'Length /= 0 then
1621
               if Arg (1) = '-' then
1622
                  if Arg'Length = 1 then
1623
                     Bad_Argument;
1624
                  end if;
1625
 
1626
                  case Arg (2) is
1627
                     when '-' =>
1628
                        if Arg'Length > Subdirs_Option'Length and then
1629
                          Arg (1 .. Subdirs_Option'Length) = Subdirs_Option
1630
                        then
1631
                           Subdirs :=
1632
                             new String'
1633
                               (Arg (Subdirs_Option'Length + 1 .. Arg'Last));
1634
 
1635
                        elsif Arg = Makeutl.Unchecked_Shared_Lib_Imports then
1636
                           Opt.Unchecked_Shared_Lib_Imports := True;
1637
 
1638
                        else
1639
                           Bad_Argument;
1640
                        end if;
1641
 
1642
                     when 'a' =>
1643
                        if Arg'Length < 4 then
1644
                           Bad_Argument;
1645
                        end if;
1646
 
1647
                        if Arg (3) = 'O' then
1648
                           Add_Lib_Search_Dir (Arg (4 .. Arg'Last));
1649
 
1650
                        elsif Arg (3) = 'P' then
1651
                           Prj.Env.Add_Directories
1652
                             (Root_Environment.Project_Path,
1653
                              Arg (4 .. Arg'Last));
1654
 
1655
                        else
1656
                           Bad_Argument;
1657
                        end if;
1658
 
1659
                     when 'c'    =>
1660
                        Compile_Only := True;
1661
 
1662
                     when 'D'    =>
1663
                        if Object_Directory_Path /= null then
1664
                           Fail ("duplicate -D switch");
1665
 
1666
                        elsif Project_File_Name /= null then
1667
                           Fail ("-P and -D cannot be used simultaneously");
1668
                        end if;
1669
 
1670
                        if Arg'Length > 2 then
1671
                           declare
1672
                              Dir : constant String := Arg (3 .. Arg'Last);
1673
                           begin
1674
                              if not Is_Directory (Dir) then
1675
                                 Fail (Dir & " is not a directory");
1676
                              else
1677
                                 Add_Lib_Search_Dir (Dir);
1678
                              end if;
1679
                           end;
1680
 
1681
                        else
1682
                           if Index = Last then
1683
                              Fail ("no directory specified after -D");
1684
                           end if;
1685
 
1686
                           Index := Index + 1;
1687
 
1688
                           declare
1689
                              Dir : constant String := Argument (Index);
1690
                           begin
1691
                              if not Is_Directory (Dir) then
1692
                                 Fail (Dir & " is not a directory");
1693
                              else
1694
                                 Add_Lib_Search_Dir (Dir);
1695
                              end if;
1696
                           end;
1697
                        end if;
1698
 
1699
                     when 'e' =>
1700
                        if Arg = "-eL" then
1701
                           Follow_Links_For_Files := True;
1702
                           Follow_Links_For_Dirs  := True;
1703
 
1704
                        else
1705
                           Bad_Argument;
1706
                        end if;
1707
 
1708
                     when 'f' =>
1709
                        Force_Deletions := True;
1710
 
1711
                     when 'F' =>
1712
                        Full_Path_Name_For_Brief_Errors := True;
1713
 
1714
                     when 'h' =>
1715
                        Usage;
1716
 
1717
                     when 'i' =>
1718
                        if Arg'Length = 2 then
1719
                           Bad_Argument;
1720
                        end if;
1721
 
1722
                        Source_Index := 0;
1723
 
1724
                        for J in 3 .. Arg'Last loop
1725
                           if Arg (J) not in '0' .. '9' then
1726
                              Bad_Argument;
1727
                           end if;
1728
 
1729
                           Source_Index :=
1730
                             (20 * Source_Index) +
1731
                             (Character'Pos (Arg (J)) - Character'Pos ('0'));
1732
                        end loop;
1733
 
1734
                     when 'I' =>
1735
                        if Arg = "-I-" then
1736
                           Opt.Look_In_Primary_Dir := False;
1737
 
1738
                        else
1739
                           if Arg'Length = 2 then
1740
                              Bad_Argument;
1741
                           end if;
1742
 
1743
                           Add_Lib_Search_Dir (Arg (3 .. Arg'Last));
1744
                        end if;
1745
 
1746
                     when 'n' =>
1747
                        Do_Nothing := True;
1748
 
1749
                     when 'P' =>
1750
                        if Project_File_Name /= null then
1751
                           Fail ("multiple -P switches");
1752
 
1753
                        elsif Object_Directory_Path /= null then
1754
                           Fail ("-D and -P cannot be used simultaneously");
1755
 
1756
                        end if;
1757
 
1758
                        if Arg'Length > 2 then
1759
                           declare
1760
                              Prj : constant String := Arg (3 .. Arg'Last);
1761
                           begin
1762
                              if Prj'Length > 1 and then
1763
                                Prj (Prj'First) = '='
1764
                              then
1765
                                 Project_File_Name :=
1766
                                   new String'
1767
                                     (Prj (Prj'First + 1 ..  Prj'Last));
1768
                              else
1769
                                 Project_File_Name := new String'(Prj);
1770
                              end if;
1771
                           end;
1772
 
1773
                        else
1774
                           if Index = Last then
1775
                              Fail ("no project specified after -P");
1776
                           end if;
1777
 
1778
                           Index := Index + 1;
1779
                           Project_File_Name := new String'(Argument (Index));
1780
                        end if;
1781
 
1782
                     when 'q' =>
1783
                        Quiet_Output := True;
1784
 
1785
                     when 'r' =>
1786
                        All_Projects := True;
1787
 
1788
                     when 'v' =>
1789
                        if Arg = "-v" then
1790
                           Verbose_Mode := True;
1791
 
1792
                        elsif Arg = "-vP0" then
1793
                           Current_Verbosity := Prj.Default;
1794
 
1795
                        elsif Arg = "-vP1" then
1796
                           Current_Verbosity := Prj.Medium;
1797
 
1798
                        elsif Arg = "-vP2" then
1799
                           Current_Verbosity := Prj.High;
1800
 
1801
                        else
1802
                           Bad_Argument;
1803
                        end if;
1804
 
1805
                     when 'X' =>
1806
                        if Arg'Length = 2 then
1807
                           Bad_Argument;
1808
                        end if;
1809
 
1810
                        declare
1811
                           Ext_Asgn  : constant String := Arg (3 .. Arg'Last);
1812
                           Start     : Positive := Ext_Asgn'First;
1813
                           Stop      : Natural  := Ext_Asgn'Last;
1814
                           OK        : Boolean  := True;
1815
 
1816
                        begin
1817
                           if Ext_Asgn (Start) = '"' then
1818
                              if Ext_Asgn (Stop) = '"' then
1819
                                 Start := Start + 1;
1820
                                 Stop  := Stop - 1;
1821
 
1822
                              else
1823
                                 OK := False;
1824
                              end if;
1825
                           end if;
1826
 
1827
                           if not OK
1828
                             or else not
1829
                               Prj.Ext.Check (Root_Environment.External,
1830
                                              Ext_Asgn (Start .. Stop))
1831
                           then
1832
                              Fail
1833
                                ("illegal external assignment '"
1834
                                 & Ext_Asgn
1835
                                 & "'");
1836
                           end if;
1837
                        end;
1838
 
1839
                     when others =>
1840
                        Bad_Argument;
1841
                  end case;
1842
 
1843
               else
1844
                  Add_File (Arg, Source_Index);
1845
               end if;
1846
            end if;
1847
         end;
1848
 
1849
         Index := Index + 1;
1850
      end loop;
1851
   end Parse_Cmd_Line;
1852
 
1853
   -----------------------
1854
   -- Repinfo_File_Name --
1855
   -----------------------
1856
 
1857
   function Repinfo_File_Name (Source : File_Name_Type) return String is
1858
   begin
1859
      return Get_Name_String (Source) & Repinfo_Suffix;
1860
   end Repinfo_File_Name;
1861
 
1862
   --------------------
1863
   -- Tree_File_Name --
1864
   --------------------
1865
 
1866
   function Tree_File_Name (Source : File_Name_Type) return String is
1867
      Src : constant String := Get_Name_String (Source);
1868
 
1869
   begin
1870
      --  If source name has an extension, then replace it with the tree suffix
1871
 
1872
      for Index in reverse Src'First + 1 .. Src'Last loop
1873
         if Src (Index) = '.' then
1874
            return Src (Src'First .. Index - 1) & Tree_Suffix;
1875
         end if;
1876
      end loop;
1877
 
1878
      --  If there is no dot, or if it is the first character, just add the
1879
      --  tree suffix.
1880
 
1881
      return Src & Tree_Suffix;
1882
   end Tree_File_Name;
1883
 
1884
   -----------
1885
   -- Usage --
1886
   -----------
1887
 
1888
   procedure Usage is
1889
   begin
1890
      if not Usage_Displayed then
1891
         Usage_Displayed := True;
1892
         Display_Copyright;
1893
         Put_Line ("Usage: gnatclean [switches] {[-innn] name}");
1894
         New_Line;
1895
 
1896
         Display_Usage_Version_And_Help;
1897
 
1898
         Put_Line ("  names is one or more file names from which " &
1899
                   "the .adb or .ads suffix may be omitted");
1900
         Put_Line ("  names may be omitted if -P<project> is specified");
1901
         New_Line;
1902
 
1903
         Put_Line ("  --subdirs=dir real obj/lib/exec dirs are subdirs");
1904
         Put_Line ("  " & Makeutl.Unchecked_Shared_Lib_Imports);
1905
         Put_Line ("       Allow shared libraries to import static libraries");
1906
         New_Line;
1907
 
1908
         Put_Line ("  -c       Only delete compiler generated files");
1909
         Put_Line ("  -D dir   Specify dir as the object library");
1910
         Put_Line ("  -eL      Follow symbolic links when processing " &
1911
                   "project files");
1912
         Put_Line ("  -f       Force deletions of unwritable files");
1913
         Put_Line ("  -F       Full project path name " &
1914
                   "in brief error messages");
1915
         Put_Line ("  -h       Display this message");
1916
         Put_Line ("  -innn    Index of unit in source for following names");
1917
         Put_Line ("  -n       Nothing to do: only list files to delete");
1918
         Put_Line ("  -Pproj   Use GNAT Project File proj");
1919
         Put_Line ("  -q       Be quiet/terse");
1920
         Put_Line ("  -r       Clean all projects recursively");
1921
         Put_Line ("  -v       Verbose mode");
1922
         Put_Line ("  -vPx     Specify verbosity when parsing " &
1923
                   "GNAT Project Files");
1924
         Put_Line ("  -Xnm=val Specify an external reference " &
1925
                   "for GNAT Project Files");
1926
         New_Line;
1927
 
1928
         Put_Line ("  -aPdir   Add directory dir to project search path");
1929
         New_Line;
1930
 
1931
         Put_Line ("  -aOdir   Specify ALI/object files search path");
1932
         Put_Line ("  -Idir    Like -aOdir");
1933
         Put_Line ("  -I-      Don't look for source/library files " &
1934
                   "in the default directory");
1935
         New_Line;
1936
      end if;
1937
   end Usage;
1938
 
1939
end Clean;

powered by: WebSVN 2.1.0

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