OSDN Git Service

2009-05-06 Thomas Quinot <quinot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / switch-m.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                             S W I T C H - M                              --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 2001-2009, Free Software Foundation, Inc.         --
10 --                                                                          --
11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
12 -- terms of the  GNU General Public License as published  by the Free Soft- --
13 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17 -- for  more details.  You should have  received  a copy of the GNU General --
18 -- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license.          --
20 --                                                                          --
21 -- GNAT was originally developed  by the GNAT team at  New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
23 --                                                                          --
24 ------------------------------------------------------------------------------
25
26 with Debug;    use Debug;
27 with Makeutl;  use Makeutl;
28 with Osint;    use Osint;
29 with Opt;      use Opt;
30 with Prj;      use Prj;
31 with Prj.Ext;  use Prj.Ext;
32 with Table;
33
34 package body Switch.M is
35
36    package Normalized_Switches is new Table.Table
37      (Table_Component_Type => String_Access,
38       Table_Index_Type     => Integer,
39       Table_Low_Bound      => 1,
40       Table_Initial        => 20,
41       Table_Increment      => 100,
42       Table_Name           => "Switch.M.Normalized_Switches");
43    --  This table is used to keep the normalized switches, so that they may be
44    --  reused for subsequent invocations of Normalize_Compiler_Switches with
45    --  similar switches.
46
47    Initial_Number_Of_Switches : constant := 10;
48
49    Global_Switches : Argument_List_Access := null;
50    --  Used by function Normalize_Compiler_Switches
51
52    ---------------------------------
53    -- Normalize_Compiler_Switches --
54    ---------------------------------
55
56    procedure Normalize_Compiler_Switches
57      (Switch_Chars : String;
58       Switches     : in out Argument_List_Access;
59       Last         : out Natural)
60    is
61       Switch_Starts_With_Gnat : Boolean;
62
63       Ptr : Integer := Switch_Chars'First;
64       Max : constant Integer := Switch_Chars'Last;
65       C   : Character := ' ';
66
67       Storing      : String := Switch_Chars;
68       First_Stored : Positive := Ptr + 1;
69       Last_Stored  : Positive := First_Stored;
70
71       procedure Add_Switch_Component (S : String);
72       --  Add a new String_Access component in Switches. If a string equal
73       --  to S is already stored in the table Normalized_Switches, use it.
74       --  Other wise add a new component to the table.
75
76       --------------------------
77       -- Add_Switch_Component --
78       --------------------------
79
80       procedure Add_Switch_Component (S : String) is
81       begin
82          --  If Switches is null, allocate a new array
83
84          if Switches = null then
85             Switches := new Argument_List (1 .. Initial_Number_Of_Switches);
86
87          --  otherwise, if Switches is full, extend it
88
89          elsif Last = Switches'Last then
90             declare
91                New_Switches : constant Argument_List_Access :=
92                                 new Argument_List
93                                       (1 .. Switches'Length + Switches'Length);
94             begin
95                New_Switches (1 .. Switches'Length) := Switches.all;
96                Last := Switches'Length;
97                Switches := New_Switches;
98             end;
99          end if;
100
101          --  If this is the first switch, Last designates the first component
102
103          if Last = 0 then
104             Last := Switches'First;
105          else
106             Last := Last + 1;
107          end if;
108
109          --  Look into the table Normalized_Switches for a similar string.
110          --  If one is found, put it at the added component, and return.
111
112          for Index in 1 .. Normalized_Switches.Last loop
113             if S = Normalized_Switches.Table (Index).all then
114                Switches (Last) := Normalized_Switches.Table (Index);
115                return;
116             end if;
117          end loop;
118
119          --  No string equal to S was found in the table Normalized_Switches.
120          --  Add a new component in the table.
121
122          Switches (Last) := new String'(S);
123          Normalized_Switches.Append (Switches (Last));
124       end Add_Switch_Component;
125
126    --  Start of processing for Normalize_Compiler_Switches
127
128    begin
129       Last := 0;
130
131       if Ptr = Max or else Switch_Chars (Ptr) /= '-' then
132          return;
133       end if;
134
135       Ptr := Ptr + 1;
136
137       Switch_Starts_With_Gnat :=
138          Ptr + 3 <= Max and then Switch_Chars (Ptr .. Ptr + 3) = "gnat";
139
140       if Switch_Starts_With_Gnat then
141          Ptr := Ptr + 4;
142          First_Stored := Ptr;
143       end if;
144
145       while Ptr <= Max loop
146          C := Switch_Chars (Ptr);
147
148          --  Processing for a switch
149
150          case Switch_Starts_With_Gnat is
151
152             when False =>
153
154                --  All switches that don't start with -gnat stay as is,
155                --  except -pg, -Wall, -k8, -w
156
157                if Switch_Chars = "-pg" or else Switch_Chars = "-p" then
158
159                   --  The gcc driver converts -pg to -p, so that is what
160                   --  is stored in the ALI file.
161
162                   Add_Switch_Component ("-p");
163
164                elsif Switch_Chars = "-Wall" then
165
166                   --  The gcc driver adds -gnatwa when -Wall is used
167
168                   Add_Switch_Component ("-gnatwa");
169                   Add_Switch_Component ("-Wall");
170
171                elsif Switch_Chars = "-k8" then
172
173                   --  The gcc driver transforms -k8 into -gnatk8
174
175                   Add_Switch_Component ("-gnatk8");
176
177                elsif Switch_Chars = "-w" then
178
179                   --  The gcc driver adds -gnatws when -w is used
180
181                   Add_Switch_Component ("-gnatws");
182                   Add_Switch_Component ("-w");
183
184                elsif Switch_Chars'Length > 6
185                  and then
186                    Switch_Chars (Switch_Chars'First .. Switch_Chars'First + 5)
187                                                              = "--RTS="
188                then
189                   Add_Switch_Component (Switch_Chars);
190
191                   --  When --RTS=mtp is used, the gcc driver adds -mrtp
192
193                   if Switch_Chars = "--RTS=mtp" then
194                      Add_Switch_Component ("-mrtp");
195                   end if;
196
197                --  Take only into account switches that are transmitted to
198                --  gnat1 by the gcc driver and stored by gnat1 in the ALI file.
199
200                else
201                   case C is
202                      when 'O' | 'W' | 'w' | 'f' | 'd' | 'g' | 'm' =>
203                         Add_Switch_Component (Switch_Chars);
204
205                      when others =>
206                         null;
207                   end case;
208                end if;
209
210                return;
211
212             when True =>
213
214                case C is
215
216                   --  One-letter switches
217
218                   when 'a' | 'A' | 'b' | 'c' | 'D' | 'E' | 'f' |
219                     'F' | 'g' | 'h' | 'H' | 'k' | 'l' | 'L' | 'n' | 'N' |
220                     'o' | 'O' | 'p' | 'P' | 'q' | 'Q' | 'r' | 's' | 't' |
221                     'u' | 'U' | 'v' | 'x' | 'X' | 'Z' =>
222                      Storing (First_Stored) := C;
223                      Add_Switch_Component
224                        (Storing (Storing'First .. First_Stored));
225                      Ptr := Ptr + 1;
226
227                   --  One-letter switches followed by a positive number
228
229                   when 'm' | 'T' =>
230                      Storing (First_Stored) := C;
231                      Last_Stored := First_Stored;
232
233                      loop
234                         Ptr := Ptr + 1;
235                         exit when Ptr > Max
236                           or else Switch_Chars (Ptr) not in '0' .. '9';
237                         Last_Stored := Last_Stored + 1;
238                         Storing (Last_Stored) := Switch_Chars (Ptr);
239                      end loop;
240
241                      Add_Switch_Component
242                        (Storing (Storing'First .. Last_Stored));
243
244                   when 'd' =>
245                      Storing (First_Stored) := 'd';
246
247                      while Ptr < Max loop
248                         Ptr := Ptr + 1;
249                         C := Switch_Chars (Ptr);
250                         exit when C = ASCII.NUL or else C = '/'
251                           or else C = '-';
252
253                         if C in '1' .. '9' or else
254                            C in 'a' .. 'z' or else
255                            C in 'A' .. 'Z'
256                         then
257                            Storing (First_Stored + 1) := C;
258                            Add_Switch_Component
259                              (Storing (Storing'First .. First_Stored + 1));
260
261                         else
262                            Last := 0;
263                            return;
264                         end if;
265                      end loop;
266
267                      return;
268
269                   when 'e' =>
270
271                      --  Store -gnateD, -gnatep= and -gnateG in the ALI file.
272                      --  The other -gnate switches do not need to be stored.
273
274                      Storing (First_Stored) := 'e';
275                      Ptr := Ptr + 1;
276
277                      if Ptr > Max
278                        or else (Switch_Chars (Ptr) /= 'D'
279                                  and then Switch_Chars (Ptr) /= 'G'
280                                  and then Switch_Chars (Ptr) /= 'p')
281                      then
282                         Last := 0;
283                         return;
284                      end if;
285
286                      --  Processing for -gnateD
287
288                      if Switch_Chars (Ptr) = 'D' then
289                         Storing (First_Stored + 1 ..
290                                  First_Stored + Max - Ptr + 1) :=
291                           Switch_Chars (Ptr .. Max);
292                         Add_Switch_Component
293                           (Storing (Storing'First ..
294                                       First_Stored + Max - Ptr + 1));
295
296                      --  Processing for -gnatep=
297
298                      elsif Switch_Chars (Ptr) = 'p' then
299                         Ptr := Ptr + 1;
300
301                         if Ptr = Max then
302                            Last := 0;
303                            return;
304                         end if;
305
306                         if Switch_Chars (Ptr) = '=' then
307                            Ptr := Ptr + 1;
308                         end if;
309
310                         --  To normalize, always put a '=' after -gnatep.
311                         --  Because that could lengthen the switch string,
312                         --  declare a local variable.
313
314                         declare
315                            To_Store : String (1 .. Max - Ptr + 9);
316                         begin
317                            To_Store (1 .. 8) := "-gnatep=";
318                            To_Store (9 .. Max - Ptr + 9) :=
319                              Switch_Chars (Ptr .. Max);
320                            Add_Switch_Component (To_Store);
321                         end;
322
323                      elsif Switch_Chars (Ptr) = 'G' then
324                         Add_Switch_Component ("-gnateG");
325                      end if;
326
327                      return;
328
329                   when 'i' =>
330                      Storing (First_Stored) := 'i';
331
332                      Ptr := Ptr + 1;
333
334                      if Ptr > Max then
335                         Last := 0;
336                         return;
337                      end if;
338
339                      C := Switch_Chars (Ptr);
340
341                      if C in '1' .. '5'
342                        or else C = '8'
343                        or else C = 'p'
344                        or else C = 'f'
345                        or else C = 'n'
346                        or else C = 'w'
347                      then
348                         Storing (First_Stored + 1) := C;
349                         Add_Switch_Component
350                           (Storing (Storing'First .. First_Stored + 1));
351                         Ptr := Ptr + 1;
352
353                      else
354                         Last := 0;
355                         return;
356                      end if;
357
358                   --  -gnatR may be followed by '0', '1', '2' or '3',
359                   --  then by 's'
360
361                   when 'R' =>
362                      Last_Stored := First_Stored;
363                      Storing (Last_Stored) := 'R';
364                      Ptr := Ptr + 1;
365
366                      if Ptr <= Max
367                        and then Switch_Chars (Ptr) in '0' .. '9'
368                      then
369                         C := Switch_Chars (Ptr);
370
371                         if C in '4' .. '9' then
372                            Last := 0;
373                            return;
374
375                         else
376                            Last_Stored := Last_Stored + 1;
377                            Storing (Last_Stored) := C;
378                            Ptr := Ptr + 1;
379
380                            if Ptr <= Max
381                              and then Switch_Chars (Ptr) = 's'
382                            then
383                               Last_Stored := Last_Stored + 1;
384                               Storing (Last_Stored) := 's';
385                               Ptr := Ptr + 1;
386                            end if;
387                         end if;
388                      end if;
389
390                      Add_Switch_Component
391                        (Storing (Storing'First .. Last_Stored));
392
393                   --  Multiple switches
394
395                   when 'V' | 'w' | 'y' =>
396                      Storing (First_Stored) := C;
397                      Ptr := Ptr + 1;
398
399                      if Ptr > Max then
400                         if C = 'y' then
401                            Add_Switch_Component
402                              (Storing (Storing'First .. First_Stored));
403
404                         else
405                            Last := 0;
406                            return;
407                         end if;
408                      end if;
409
410                      while Ptr <= Max loop
411                         C := Switch_Chars (Ptr);
412                         Ptr := Ptr + 1;
413
414                         --  -gnatyMxxx
415
416                         if C = 'M' and then Storing (First_Stored) = 'y' then
417                            Last_Stored := First_Stored + 1;
418                            Storing (Last_Stored) := 'M';
419                            while Ptr <= Max loop
420                               C := Switch_Chars (Ptr);
421                               exit when C not in '0' .. '9';
422                               Last_Stored := Last_Stored + 1;
423                               Storing (Last_Stored) := C;
424                               Ptr := Ptr + 1;
425                            end loop;
426
427                            --  If there is no digit after -gnatyM,
428                            --  the switch is invalid.
429
430                            if Last_Stored = First_Stored + 1 then
431                               Last := 0;
432                               return;
433
434                            else
435                               Add_Switch_Component
436                                 (Storing (Storing'First .. Last_Stored));
437                            end if;
438
439                            --  All other switches are -gnatxx
440
441                         else
442                            Storing (First_Stored + 1) := C;
443                            Add_Switch_Component
444                              (Storing (Storing'First .. First_Stored + 1));
445                         end if;
446                      end loop;
447
448                   --  -gnat95 -gnat05
449
450                   when '0' | '9' =>
451                      Last_Stored := First_Stored;
452                      Storing (Last_Stored) := C;
453                      Ptr := Ptr + 1;
454
455                      if Ptr /= Max or else Switch_Chars (Ptr) /= '5' then
456
457                         --  Invalid switch
458
459                         Last := 0;
460                         return;
461
462                      else
463                         Last_Stored := Last_Stored + 1;
464                         Storing (Last_Stored) := '5';
465                         Add_Switch_Component
466                           (Storing (Storing'First .. Last_Stored));
467                         Ptr := Ptr + 1;
468                      end if;
469
470                   --  -gnat83
471
472                   when '8' =>
473                      Last_Stored := First_Stored;
474                      Storing (Last_Stored) := '8';
475                      Ptr := Ptr + 1;
476
477                      if Ptr /= Max or else Switch_Chars (Ptr) /= '3' then
478
479                         --  Invalid switch
480
481                         Last := 0;
482                         return;
483
484                      else
485                         Last_Stored := Last_Stored + 1;
486                         Storing (Last_Stored) := '3';
487                         Add_Switch_Component
488                           (Storing (Storing'First .. Last_Stored));
489                         Ptr := Ptr + 1;
490                      end if;
491
492                   --  Not a valid switch
493
494                   when others =>
495                      Last := 0;
496                      return;
497
498                end case;
499
500          end case;
501       end loop;
502    end Normalize_Compiler_Switches;
503
504    function Normalize_Compiler_Switches
505      (Switch_Chars : String)
506       return         Argument_List
507    is
508       Last : Natural;
509
510    begin
511       Normalize_Compiler_Switches (Switch_Chars, Global_Switches, Last);
512
513       if Last = 0 then
514          return (1 .. 0 => null);
515       else
516          return Global_Switches (Global_Switches'First .. Last);
517       end if;
518
519    end Normalize_Compiler_Switches;
520
521    ------------------------
522    -- Scan_Make_Switches --
523    ------------------------
524
525    procedure Scan_Make_Switches
526      (Switch_Chars : String;
527       Success      : out Boolean)
528    is
529       Ptr : Integer          := Switch_Chars'First;
530       Max : constant Integer := Switch_Chars'Last;
531       C   : Character        := ' ';
532
533    begin
534       --  Assume a good switch
535
536       Success := True;
537
538       --  Skip past the initial character (must be the switch character)
539
540       if Ptr = Max then
541          Bad_Switch (Switch_Chars);
542
543       else
544          Ptr := Ptr + 1;
545       end if;
546
547       --  A little check, "gnat" at the start of a switch is for the compiler
548
549       if Switch_Chars'Length >= Ptr + 3
550         and then Switch_Chars (Ptr .. Ptr + 3) = "gnat"
551       then
552          Success := False;
553          return;
554       end if;
555
556       C := Switch_Chars (Ptr);
557
558       --  Multiple character switches
559
560       if Switch_Chars'Length > 2 then
561          if Switch_Chars = "--create-missing-dirs" then
562             Setup_Projects := True;
563
564          elsif Switch_Chars'Length > Subdirs_Option'Length
565            and then
566              Switch_Chars
567                (Switch_Chars'First ..
568                 Switch_Chars'First + Subdirs_Option'Length - 1) =
569                                                             Subdirs_Option
570          then
571             Subdirs :=
572               new String'
573                 (Switch_Chars
574                   (Switch_Chars'First + Subdirs_Option'Length ..
575                    Switch_Chars'Last));
576
577          elsif Switch_Chars (Ptr) = '-' then
578             Bad_Switch (Switch_Chars);
579
580          elsif Switch_Chars'Length > 3
581            and then Switch_Chars (Ptr .. Ptr + 1) = "aP"
582          then
583             Add_Search_Project_Directory
584               (Switch_Chars (Ptr + 2 .. Switch_Chars'Last));
585
586          elsif C = 'v' and then Switch_Chars'Length = 3 then
587             Ptr := Ptr + 1;
588             Verbose_Mode := True;
589
590             case Switch_Chars (Ptr) is
591                when 'l' =>
592                   Verbosity_Level := Opt.Low;
593
594                when 'm' =>
595                   Verbosity_Level := Opt.Medium;
596
597                when 'h' =>
598                   Verbosity_Level := Opt.High;
599
600                when others =>
601                   Success := False;
602             end case;
603
604          elsif C = 'd' then
605
606             --  Note: for the debug switch, the remaining characters in this
607             --  switch field must all be debug flags, since all valid switch
608             --  characters are also valid debug characters. This switch is not
609             --  documented on purpose because it is only used by the
610             --  implementors.
611
612             --  Loop to scan out debug flags
613
614             while Ptr < Max loop
615                Ptr := Ptr + 1;
616                C := Switch_Chars (Ptr);
617
618                if C in 'a' .. 'z' or else C in 'A' .. 'Z' then
619                   Set_Debug_Flag (C);
620                else
621                   Bad_Switch (Switch_Chars);
622                end if;
623             end loop;
624
625          elsif C = 'e' then
626             Ptr := Ptr + 1;
627
628             case Switch_Chars (Ptr) is
629
630                --  Processing for eI switch
631
632                when 'I' =>
633                   Ptr := Ptr + 1;
634                   Scan_Pos (Switch_Chars, Max, Ptr, Main_Index, C);
635
636                   if Ptr <= Max then
637                      Bad_Switch (Switch_Chars);
638                   end if;
639
640                --  Processing for eL switch
641
642                when 'L' =>
643                   if Ptr /= Max then
644                      Bad_Switch (Switch_Chars);
645
646                   else
647                      Follow_Links_For_Files := True;
648                   end if;
649
650                --  Processing for eS switch
651
652                when 'S' =>
653                   if Ptr /= Max then
654                      Bad_Switch (Switch_Chars);
655
656                   else
657                      Commands_To_Stdout := True;
658                   end if;
659
660                when others =>
661                   Bad_Switch (Switch_Chars);
662             end case;
663
664          elsif C = 'j' then
665             Ptr := Ptr + 1;
666
667             declare
668                Max_Proc : Pos;
669             begin
670                Scan_Pos (Switch_Chars, Max, Ptr, Max_Proc, C);
671
672                if Ptr <= Max then
673                   Bad_Switch (Switch_Chars);
674
675                else
676                   Maximum_Processes := Positive (Max_Proc);
677                end if;
678             end;
679
680          elsif C = 'w' and then Switch_Chars'Length = 3 then
681             Ptr := Ptr + 1;
682
683             if Switch_Chars = "-we" then
684                Warning_Mode := Treat_As_Error;
685
686             elsif Switch_Chars = "-wn" then
687                Warning_Mode := Normal;
688
689             elsif Switch_Chars = "-ws" then
690                Warning_Mode  := Suppress;
691
692             else
693                Success := False;
694             end if;
695
696          else
697             Success := False;
698          end if;
699
700       --  Single-character switches
701
702       else
703          Check_Switch : begin
704
705             case C is
706
707                when 'a' =>
708                   Check_Readonly_Files := True;
709
710                --  Processing for b switch
711
712                when 'b' =>
713                   Bind_Only  := True;
714                   Make_Steps := True;
715
716                --  Processing for B switch
717
718                when 'B' =>
719                   Build_Bind_And_Link_Full_Project := True;
720
721                --  Processing for c switch
722
723                when 'c' =>
724                   Compile_Only := True;
725                   Make_Steps   := True;
726
727                --  Processing for C switch
728
729                when 'C' =>
730                   Create_Mapping_File := True;
731
732                --  Processing for D switch
733
734                when 'D' =>
735                   if Object_Directory_Present then
736                      Osint.Fail ("duplicate -D switch");
737
738                   else
739                      Object_Directory_Present := True;
740                   end if;
741
742                --  Processing for f switch
743
744                when 'f' =>
745                   Force_Compilations := True;
746
747                --  Processing for F switch
748
749                when 'F' =>
750                   Full_Path_Name_For_Brief_Errors := True;
751
752                --  Processing for h switch
753
754                when 'h' =>
755                   Usage_Requested := True;
756
757                --  Processing for i switch
758
759                when 'i' =>
760                   In_Place_Mode := True;
761
762                --  Processing for j switch
763
764                when 'j' =>
765                   --  -j not followed by a number is an error
766
767                   Bad_Switch (Switch_Chars);
768
769                --  Processing for k switch
770
771                when 'k' =>
772                   Keep_Going := True;
773
774                --  Processing for l switch
775
776                when 'l' =>
777                   Link_Only  := True;
778                   Make_Steps := True;
779
780                --  Processing for M switch
781
782                when 'M' =>
783                   List_Dependencies := True;
784
785                --  Processing for n switch
786
787                when 'n' =>
788                   Do_Not_Execute := True;
789
790                --  Processing for o switch
791
792                when 'o' =>
793                   if Output_File_Name_Present then
794                      Osint.Fail ("duplicate -o switch");
795                   else
796                      Output_File_Name_Present := True;
797                   end if;
798
799                --  Processing for p switch
800
801                when 'p' =>
802                   Setup_Projects := True;
803
804                --  Processing for q switch
805
806                when 'q' =>
807                   Quiet_Output := True;
808
809                --  Processing for R switch
810
811                when 'R' =>
812                   Run_Path_Option := False;
813
814                --  Processing for s switch
815
816                when 's' =>
817                   Ptr := Ptr + 1;
818                   Check_Switches := True;
819
820                --  Processing for v switch
821
822                when 'v' =>
823                   Verbose_Mode := True;
824                   Verbosity_Level := Opt.High;
825
826                   --  Processing for x switch
827
828                when 'x' =>
829                   External_Unit_Compilation_Allowed := True;
830
831                   --  Processing for z switch
832
833                when 'z' =>
834                   No_Main_Subprogram := True;
835
836                   --  Any other small letter is an illegal switch
837
838                when others =>
839                   if C in 'a' .. 'z' then
840                      Bad_Switch (Switch_Chars);
841
842                   else
843                      Success := False;
844                   end if;
845
846             end case;
847          end Check_Switch;
848       end if;
849    end Scan_Make_Switches;
850
851 end Switch.M;