OSDN Git Service

2007-04-20 Vincent Celier <celier@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-2007, 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 2,  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 COPYING.  If not, write --
19 -- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
20 -- Boston, MA 02110-1301, USA.                                              --
21 --                                                                          --
22 -- GNAT was originally developed  by the GNAT team at  New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
24 --                                                                          --
25 ------------------------------------------------------------------------------
26
27 with Debug;    use Debug;
28 with Osint;    use Osint;
29 with Opt;      use Opt;
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.Increment_Last;
123          Normalized_Switches.Table (Normalized_Switches.Last) :=
124            Switches (Last);
125       end Add_Switch_Component;
126
127    --  Start of processing for Normalize_Compiler_Switches
128
129    begin
130       Last := 0;
131
132       if Ptr = Max or else Switch_Chars (Ptr) /= '-' then
133          return;
134       end if;
135
136       Ptr := Ptr + 1;
137
138       Switch_Starts_With_Gnat :=
139          Ptr + 3 <= Max and then Switch_Chars (Ptr .. Ptr + 3) = "gnat";
140
141       if Switch_Starts_With_Gnat then
142          Ptr := Ptr + 4;
143          First_Stored := Ptr;
144       end if;
145
146       while Ptr <= Max loop
147          C := Switch_Chars (Ptr);
148
149          --  Processing for a switch
150
151          case Switch_Starts_With_Gnat is
152
153             when False =>
154
155                --  All switches that don't start with -gnat stay as is,
156                --  except -v, -E and -pg
157
158                if Switch_Chars = "-pg" then
159
160                   --  The gcc driver converts -pg to -p, so that is what
161                   --  is stored in the ALI file.
162
163                   Add_Switch_Component ("-p");
164
165                --  Do not take into account switches that are not transmitted
166                --  to gnat1 by the gcc driver.
167
168                elsif C /= 'v' and then C /= 'E' then
169                   Add_Switch_Component (Switch_Chars);
170                end if;
171
172                return;
173
174             when True =>
175
176                case C is
177
178                   --  One-letter switches
179
180                   when 'a' | 'A' | 'b' | 'c' | 'D' | 'E' | 'f' |
181                     'F' | 'g' | 'h' | 'H' | 'k' | 'l' | 'L' | 'n' | 'N' |
182                     'o' | 'O' | 'p' | 'P' | 'q' | 'Q' | 'r' | 's' | 't' |
183                     'u' | 'U' | 'v' | 'x' | 'X' | 'Z' =>
184                      Storing (First_Stored) := C;
185                      Add_Switch_Component
186                        (Storing (Storing'First .. First_Stored));
187                      Ptr := Ptr + 1;
188
189                   --  One-letter switches followed by a positive number
190
191                   when 'm' | 'T' =>
192                      Storing (First_Stored) := C;
193                      Last_Stored := First_Stored;
194
195                      loop
196                         Ptr := Ptr + 1;
197                         exit when Ptr > Max
198                           or else Switch_Chars (Ptr) not in '0' .. '9';
199                         Last_Stored := Last_Stored + 1;
200                         Storing (Last_Stored) := Switch_Chars (Ptr);
201                      end loop;
202
203                      Add_Switch_Component
204                        (Storing (Storing'First .. Last_Stored));
205
206                   when 'd' =>
207                      Storing (First_Stored) := 'd';
208
209                      while Ptr < Max loop
210                         Ptr := Ptr + 1;
211                         C := Switch_Chars (Ptr);
212                         exit when C = ASCII.NUL or else C = '/'
213                           or else C = '-';
214
215                         if C in '1' .. '9' or else
216                            C in 'a' .. 'z' or else
217                            C in 'A' .. 'Z'
218                         then
219                            Storing (First_Stored + 1) := C;
220                            Add_Switch_Component
221                              (Storing (Storing'First .. First_Stored + 1));
222
223                         else
224                            Last := 0;
225                            return;
226                         end if;
227                      end loop;
228
229                      return;
230
231                   when 'e' =>
232
233                      --  Only -gnateD and -gnatep= need storing in ALI file
234
235                      Storing (First_Stored) := 'e';
236                      Ptr := Ptr + 1;
237
238                      if Ptr > Max
239                        or else (Switch_Chars (Ptr) /= 'D'
240                                   and then Switch_Chars (Ptr) /= 'p')
241                      then
242                         Last := 0;
243                         return;
244                      end if;
245
246                      --  Processing for -gnateD
247
248                      if Switch_Chars (Ptr) = 'D' then
249                         Storing (First_Stored + 1 ..
250                                  First_Stored + Max - Ptr + 1) :=
251                           Switch_Chars (Ptr .. Max);
252                         Add_Switch_Component
253                           (Storing (Storing'First ..
254                                       First_Stored + Max - Ptr + 1));
255
256                      --  Processing for -gnatep=
257
258                      else
259                         Ptr := Ptr + 1;
260
261                         if Ptr = Max then
262                            Last := 0;
263                            return;
264                         end if;
265
266                         if Switch_Chars (Ptr) = '=' then
267                            Ptr := Ptr + 1;
268                         end if;
269
270                         --  To normalize, always put a '=' after -gnatep.
271                         --  Because that could lengthen the switch string,
272                         --  declare a local variable.
273
274                         declare
275                            To_Store : String (1 .. Max - Ptr + 9);
276                         begin
277                            To_Store (1 .. 8) := "-gnatep=";
278                            To_Store (9 .. Max - Ptr + 9) :=
279                              Switch_Chars (Ptr .. Max);
280                            Add_Switch_Component (To_Store);
281                         end;
282                      end if;
283
284                      return;
285
286                   when 'i' =>
287                      Storing (First_Stored) := 'i';
288
289                      Ptr := Ptr + 1;
290
291                      if Ptr > Max then
292                         Last := 0;
293                         return;
294                      end if;
295
296                      C := Switch_Chars (Ptr);
297
298                      if C in '1' .. '5'
299                        or else C = '8'
300                        or else C = 'p'
301                        or else C = 'f'
302                        or else C = 'n'
303                        or else C = 'w'
304                      then
305                         Storing (First_Stored + 1) := C;
306                         Add_Switch_Component
307                           (Storing (Storing'First .. First_Stored + 1));
308                         Ptr := Ptr + 1;
309
310                      else
311                         Last := 0;
312                         return;
313                      end if;
314
315                   --  -gnatR may be followed by '0', '1', '2' or '3',
316                   --  then by 's'
317
318                   when 'R' =>
319                      Last_Stored := First_Stored;
320                      Storing (Last_Stored) := 'R';
321                      Ptr := Ptr + 1;
322
323                      if Ptr <= Max
324                        and then Switch_Chars (Ptr) in '0' .. '9'
325                      then
326                         C := Switch_Chars (Ptr);
327
328                         if C in '4' .. '9' then
329                            Last := 0;
330                            return;
331
332                         else
333                            Last_Stored := Last_Stored + 1;
334                            Storing (Last_Stored) := C;
335                            Ptr := Ptr + 1;
336
337                            if Ptr <= Max
338                              and then Switch_Chars (Ptr) = 's' then
339                               Last_Stored := Last_Stored + 1;
340                               Storing (Last_Stored) := 's';
341                               Ptr := Ptr + 1;
342                            end if;
343                         end if;
344                      end if;
345
346                      Add_Switch_Component
347                        (Storing (Storing'First .. Last_Stored));
348
349                   --  Multiple switches
350
351                   when 'V' | 'w' | 'y' =>
352                      Storing (First_Stored) := C;
353                      Ptr := Ptr + 1;
354
355                      if Ptr > Max then
356                         if C = 'y' then
357                            Add_Switch_Component
358                              (Storing (Storing'First .. First_Stored));
359
360                         else
361                            Last := 0;
362                            return;
363                         end if;
364                      end if;
365
366                      while Ptr <= Max loop
367                         C := Switch_Chars (Ptr);
368                         Ptr := Ptr + 1;
369
370                         --  -gnatyMxxx
371
372                         if C = 'M' and then
373                           Storing (First_Stored) = 'y'
374                         then
375                            Last_Stored := First_Stored + 1;
376                            Storing (Last_Stored) := 'M';
377
378                            while Ptr <= Max loop
379                               C := Switch_Chars (Ptr);
380                               exit when C not in '0' .. '9';
381                               Last_Stored := Last_Stored + 1;
382                               Storing (Last_Stored) := C;
383                               Ptr := Ptr + 1;
384                            end loop;
385
386                            --  If there is no digit after -gnatyM,
387                            --  the switch is invalid.
388
389                            if Last_Stored = First_Stored + 1 then
390                               Last := 0;
391                               return;
392
393                            else
394                               Add_Switch_Component
395                                 (Storing (Storing'First .. Last_Stored));
396                            end if;
397
398                            --  All other switches are -gnatxx
399
400                         else
401                            Storing (First_Stored + 1) := C;
402                            Add_Switch_Component
403                              (Storing (Storing'First .. First_Stored + 1));
404                         end if;
405                      end loop;
406
407                   --  -gnat95 -gnat05
408
409                   when '0' | '9' =>
410                      Last_Stored := First_Stored;
411                      Storing (Last_Stored) := C;
412                      Ptr := Ptr + 1;
413
414                      if Ptr /= Max or else Switch_Chars (Ptr) /= '5' then
415
416                         --  Invalid switch
417
418                         Last := 0;
419                         return;
420
421                      else
422                         Last_Stored := Last_Stored + 1;
423                         Storing (Last_Stored) := '5';
424                         Add_Switch_Component
425                           (Storing (Storing'First .. Last_Stored));
426                         Ptr := Ptr + 1;
427                      end if;
428
429                   --  -gnat83
430
431                   when '8' =>
432                      Last_Stored := First_Stored;
433                      Storing (Last_Stored) := '8';
434                      Ptr := Ptr + 1;
435
436                      if Ptr /= Max or else Switch_Chars (Ptr) /= '3' then
437
438                         --  Invalid switch
439
440                         Last := 0;
441                         return;
442
443                      else
444                         Last_Stored := Last_Stored + 1;
445                         Storing (Last_Stored) := '3';
446                         Add_Switch_Component
447                           (Storing (Storing'First .. Last_Stored));
448                         Ptr := Ptr + 1;
449                      end if;
450
451                   --  Not a valid switch
452
453                   when others =>
454                      Last := 0;
455                      return;
456
457                end case;
458
459          end case;
460       end loop;
461    end Normalize_Compiler_Switches;
462
463    function Normalize_Compiler_Switches
464      (Switch_Chars : String)
465       return         Argument_List
466    is
467       Last : Natural;
468
469    begin
470       Normalize_Compiler_Switches (Switch_Chars, Global_Switches, Last);
471
472       if Last = 0 then
473          return (1 .. 0 => null);
474       else
475          return Global_Switches (Global_Switches'First .. Last);
476       end if;
477
478    end Normalize_Compiler_Switches;
479
480    ------------------------
481    -- Scan_Make_Switches --
482    ------------------------
483
484    procedure Scan_Make_Switches
485      (Switch_Chars : String;
486       Success      : out Boolean)
487    is
488       Ptr : Integer          := Switch_Chars'First;
489       Max : constant Integer := Switch_Chars'Last;
490       C   : Character        := ' ';
491
492    begin
493       --  Assume a good switch
494
495       Success := True;
496
497       --  Skip past the initial character (must be the switch character)
498
499       if Ptr = Max then
500          Bad_Switch (Switch_Chars);
501
502       else
503          Ptr := Ptr + 1;
504       end if;
505
506       --  A little check, "gnat" at the start of a switch is for the compiler
507
508       if Switch_Chars'Length >= Ptr + 3
509         and then Switch_Chars (Ptr .. Ptr + 3) = "gnat"
510       then
511          Success := False;
512          return;
513       end if;
514
515       C := Switch_Chars (Ptr);
516
517       --  Multiple character switches
518
519       if Switch_Chars'Length > 2 then
520          if Switch_Chars = "--create-missing-dirs" then
521             Setup_Projects := True;
522
523          elsif Switch_Chars'Length > 3 and then
524                Switch_Chars (Ptr .. Ptr + 1) = "aP"
525          then
526             Add_Search_Project_Directory
527               (Switch_Chars (Ptr + 2 .. Switch_Chars'Last));
528
529          elsif C = 'v' and then Switch_Chars'Length = 3 then
530             Ptr := Ptr + 1;
531             Verbose_Mode := True;
532
533             case Switch_Chars (Ptr) is
534                when 'l' =>
535                   Verbosity_Level := Opt.Low;
536
537                when 'm' =>
538                   Verbosity_Level := Opt.Medium;
539
540                when 'h' =>
541                   Verbosity_Level := Opt.High;
542
543                when others =>
544                   Success := False;
545             end case;
546
547          elsif C = 'd' then
548
549             --  Note: for the debug switch, the remaining characters in this
550             --  switch field must all be debug flags, since all valid switch
551             --  characters are also valid debug characters. This switch is not
552             --  documented on purpose because it is only used by the
553             --  implementors.
554
555             --  Loop to scan out debug flags
556
557             while Ptr < Max loop
558                Ptr := Ptr + 1;
559                C := Switch_Chars (Ptr);
560
561                if C in 'a' .. 'z' or else C in 'A' .. 'Z' then
562                   Set_Debug_Flag (C);
563                else
564                   Bad_Switch (Switch_Chars);
565                end if;
566             end loop;
567
568          elsif C = 'e' then
569             Ptr := Ptr + 1;
570
571             case Switch_Chars (Ptr) is
572
573                --  Processing for eI switch
574
575                when 'I' =>
576                   Ptr := Ptr + 1;
577                   Scan_Pos (Switch_Chars, Max, Ptr, Main_Index, C);
578
579                   if Ptr <= Max then
580                      Bad_Switch (Switch_Chars);
581                   end if;
582
583                --  Processing for eL switch
584
585                when 'L' =>
586                   if Ptr /= Max then
587                      Bad_Switch (Switch_Chars);
588
589                   else
590                      Follow_Links := True;
591                   end if;
592
593                --  Processing for eS switch
594
595                when 'S' =>
596                   if Ptr /= Max then
597                      Bad_Switch (Switch_Chars);
598
599                   else
600                      Commands_To_Stdout := True;
601                   end if;
602
603                when others =>
604                   Bad_Switch (Switch_Chars);
605             end case;
606
607          elsif C = 'j' then
608             Ptr := Ptr + 1;
609
610             declare
611                Max_Proc : Pos;
612             begin
613                Scan_Pos (Switch_Chars, Max, Ptr, Max_Proc, C);
614
615                if Ptr <= Max then
616                   Bad_Switch (Switch_Chars);
617
618                else
619                   Maximum_Processes := Positive (Max_Proc);
620                end if;
621             end;
622
623          elsif C = 'w' and then Switch_Chars'Length = 3 then
624             Ptr := Ptr + 1;
625
626             if Switch_Chars = "-we" then
627                Warning_Mode := Treat_As_Error;
628
629             elsif Switch_Chars = "-wn" then
630                Warning_Mode := Normal;
631
632             elsif Switch_Chars = "-ws" then
633                Warning_Mode  := Suppress;
634
635             else
636                Success := False;
637             end if;
638
639          else
640             Success := False;
641          end if;
642
643       --  Single-character switches
644
645       else
646          Check_Switch : begin
647
648             case C is
649
650                when 'a' =>
651                   Check_Readonly_Files := True;
652
653                --  Processing for b switch
654
655                when 'b' =>
656                   Bind_Only  := True;
657                   Make_Steps := True;
658
659                --  Processing for B switch
660
661                when 'B' =>
662                   Build_Bind_And_Link_Full_Project := True;
663
664                --  Processing for c switch
665
666                when 'c' =>
667                   Compile_Only := True;
668                   Make_Steps   := True;
669
670                --  Processing for C switch
671
672                when 'C' =>
673                   Create_Mapping_File := True;
674
675                --  Processing for D switch
676
677                when 'D' =>
678                   if Object_Directory_Present then
679                      Osint.Fail ("duplicate -D switch");
680
681                   else
682                      Object_Directory_Present := True;
683                   end if;
684
685                --  Processing for f switch
686
687                when 'f' =>
688                   Force_Compilations := True;
689
690                --  Processing for F switch
691
692                when 'F' =>
693                   Full_Path_Name_For_Brief_Errors := True;
694
695                --  Processing for h switch
696
697                when 'h' =>
698                   Usage_Requested := True;
699
700                --  Processing for i switch
701
702                when 'i' =>
703                   In_Place_Mode := True;
704
705                --  Processing for j switch
706
707                when 'j' =>
708                   --  -j not followed by a number is an error
709
710                   Bad_Switch (Switch_Chars);
711
712                --  Processing for k switch
713
714                when 'k' =>
715                   Keep_Going := True;
716
717                --  Processing for l switch
718
719                when 'l' =>
720                   Link_Only  := True;
721                   Make_Steps := True;
722
723                --  Processing for M switch
724
725                when 'M' =>
726                   List_Dependencies := True;
727
728                --  Processing for n switch
729
730                when 'n' =>
731                   Do_Not_Execute := True;
732
733                --  Processing for o switch
734
735                when 'o' =>
736                   if Output_File_Name_Present then
737                      Osint.Fail ("duplicate -o switch");
738                   else
739                      Output_File_Name_Present := True;
740                   end if;
741
742                --  Processing for p switch
743
744                when 'p' =>
745                   Setup_Projects := True;
746
747                --  Processing for q switch
748
749                when 'q' =>
750                   Quiet_Output := True;
751
752                --  Processing for R switch
753
754                when 'R' =>
755                   Run_Path_Option := False;
756
757                --  Processing for s switch
758
759                when 's' =>
760                   Ptr := Ptr + 1;
761                   Check_Switches := True;
762
763                --  Processing for v switch
764
765                when 'v' =>
766                   Verbose_Mode := True;
767                   Verbosity_Level := Opt.High;
768
769                   --  Processing for x switch
770
771                when 'x' =>
772                   External_Unit_Compilation_Allowed := True;
773
774                   --  Processing for z switch
775
776                when 'z' =>
777                   No_Main_Subprogram := True;
778
779                   --  Any other small letter is an illegal switch
780
781                when others =>
782                   if C in 'a' .. 'z' then
783                      Bad_Switch (Switch_Chars);
784
785                   else
786                      Success := False;
787                   end if;
788
789             end case;
790          end Check_Switch;
791       end if;
792    end Scan_Make_Switches;
793
794 end Switch.M;