OSDN Git Service

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