OSDN Git Service

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