OSDN Git Service

* 1aexcept.adb, 1aexcept.ads, 1ic.ads, 1ssecsta.adb,
[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-2002 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,  59 Temple Place - Suite 330,  Boston, --
20 -- MA 02111-1307, 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.C.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       First_Char   : Integer := Ptr;
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 : Argument_List_Access := 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          if Last = 0 then
101             Last := Switches'First;
102
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          First_Char := Ptr;
147          C := Switch_Chars (Ptr);
148
149          --  Processing for a switch
150
151          case Switch_Starts_With_Gnat is
152
153             when False =>
154                --  All switches that don't start with -gnat stay as is
155
156                Add_Switch_Component (Switch_Chars);
157                return;
158
159             when True =>
160
161                case C is
162
163                   --  One-letter switches
164
165                   when 'a' | 'A' | 'b' | 'c' | 'C' | 'D' | 'E' | 'f' |
166                     'F' | 'g' | 'h' | 'H' | 'k' | 'l' | 'L' | 'n' | 'N' |
167                     'o' | 'O' | 'p' | 'P' | 'q' | 'Q' | 'r' | 's' | 't' |
168                     'u' | 'U' | 'v' | 'x' | 'X' | 'Z' =>
169                      Storing (First_Stored) := C;
170                      Add_Switch_Component
171                        (Storing (Storing'First .. First_Stored));
172                      Ptr := Ptr + 1;
173
174                   --  One-letter switches followed by a positive number
175
176                   when 'm' | 'T' =>
177                      Storing (First_Stored) := C;
178                      Last_Stored := First_Stored;
179
180                      loop
181                         Ptr := Ptr + 1;
182                         exit when Ptr > Max
183                           or else Switch_Chars (Ptr) not in '0' .. '9';
184                         Last_Stored := Last_Stored + 1;
185                         Storing (Last_Stored) := Switch_Chars (Ptr);
186                      end loop;
187
188                      Add_Switch_Component
189                        (Storing (Storing'First .. Last_Stored));
190
191                   when 'd' =>
192                      Storing (First_Stored) := 'd';
193
194                      while Ptr < Max loop
195                         Ptr := Ptr + 1;
196                         C := Switch_Chars (Ptr);
197                         exit when C = ASCII.NUL or else C = '/'
198                           or else C = '-';
199
200                         if C in '1' .. '9' or else
201                            C in 'a' .. 'z' or else
202                            C in 'A' .. 'Z'
203                         then
204                            Storing (First_Stored + 1) := C;
205                            Add_Switch_Component
206                              (Storing (Storing'First .. First_Stored + 1));
207
208                         else
209                            Last := 0;
210                            return;
211                         end if;
212                      end loop;
213
214                      return;
215
216                   when 'e' =>
217                      --  None of the -gnate switches (-gnatec and -gnatem)
218                      --  need to be store in an ALI file.
219
220                      return;
221
222                   when 'i' =>
223                      Storing (First_Stored) := 'i';
224
225                      Ptr := Ptr + 1;
226
227                      if Ptr > Max then
228                         Last := 0;
229                         return;
230                      end if;
231
232                      C := Switch_Chars (Ptr);
233
234                      if C in '1' .. '5'
235                        or else C = '8'
236                        or else C = 'p'
237                        or else C = 'f'
238                        or else C = 'n'
239                        or else C = 'w'
240                      then
241                         Storing (First_Stored + 1) := C;
242                         Add_Switch_Component
243                           (Storing (Storing'First .. First_Stored + 1));
244                         Ptr := Ptr + 1;
245
246                      else
247                         Last := 0;
248                         return;
249                      end if;
250
251                   --  -gnatR may be followed by '0', '1', '2' or '3',
252                   --  then by 's'
253
254                   when 'R' =>
255                      Last_Stored := First_Stored;
256                      Storing (Last_Stored) := 'R';
257                      Ptr := Ptr + 1;
258
259                      if Ptr <= Max
260                        and then Switch_Chars (Ptr) in '0' .. '9'
261                      then
262                         C := Switch_Chars (Ptr);
263
264                         if C in '4' .. '9' then
265                            Last := 0;
266                            return;
267
268                         else
269                            Last_Stored := Last_Stored + 1;
270                            Storing (Last_Stored) := C;
271                            Ptr := Ptr + 1;
272
273                            if Ptr <= Max
274                              and then Switch_Chars (Ptr) = 's' then
275                               Last_Stored := Last_Stored + 1;
276                               Storing (Last_Stored) := 's';
277                               Ptr := Ptr + 1;
278                            end if;
279                         end if;
280                      end if;
281
282                      Add_Switch_Component
283                        (Storing (Storing'First .. Last_Stored));
284
285                   --  Multiple switches
286
287                   when 'V' | 'w' | 'y' =>
288                      Storing (First_Stored) := C;
289                      Ptr := Ptr + 1;
290
291                      if Ptr > Max then
292                         if C = 'y' then
293                            Add_Switch_Component
294                              (Storing (Storing'First .. First_Stored));
295
296                         else
297                            Last := 0;
298                            return;
299                         end if;
300                      end if;
301
302                      while Ptr <= Max loop
303                         C := Switch_Chars (Ptr);
304                         Ptr := Ptr + 1;
305
306                         --  'w' should be skipped in -gnatw
307
308                         if C /= 'w' or else Storing (First_Stored) /= 'w' then
309
310                            --  -gnatyMxxx
311
312                            if C = 'M'
313                              and then Storing (First_Stored) = 'y' then
314                               Last_Stored := First_Stored + 1;
315                               Storing (Last_Stored) := 'M';
316
317                               while Ptr <= Max loop
318                                  C := Switch_Chars (Ptr);
319                                  exit when C not in '0' .. '9';
320                                  Last_Stored := Last_Stored + 1;
321                                  Storing (Last_Stored) := C;
322                                  Ptr := Ptr + 1;
323                               end loop;
324
325                               --  If there is no digit after -gnatyM,
326                               --  the switch is invalid.
327
328                               if Last_Stored = First_Stored + 1 then
329                                  Last := 0;
330                                  return;
331
332                               else
333                                  Add_Switch_Component
334                                    (Storing (Storing'First .. Last_Stored));
335                               end if;
336
337                            --  All other switches are -gnatxx
338
339                            else
340                               Storing (First_Stored + 1) := C;
341                               Add_Switch_Component
342                                 (Storing (Storing'First .. First_Stored + 1));
343                            end if;
344                         end if;
345                      end loop;
346
347                   --  Not a valid switch
348
349                   when others =>
350                      Last := 0;
351                      return;
352
353                end case;
354
355          end case;
356       end loop;
357    end Normalize_Compiler_Switches;
358
359    function Normalize_Compiler_Switches
360      (Switch_Chars : String)
361       return         Argument_List
362    is
363       Last : Natural;
364
365    begin
366       Normalize_Compiler_Switches (Switch_Chars, Global_Switches, Last);
367
368       if Last = 0 then
369          return (1 .. 0 => null);
370
371       else
372          return Global_Switches (Global_Switches'First .. Last);
373       end if;
374
375    end Normalize_Compiler_Switches;
376
377    ------------------------
378    -- Scan_Make_Switches --
379    ------------------------
380
381    procedure Scan_Make_Switches (Switch_Chars : String) is
382       Ptr : Integer := Switch_Chars'First;
383       Max : Integer := Switch_Chars'Last;
384       C   : Character := ' ';
385
386    begin
387       --  Skip past the initial character (must be the switch character)
388
389       if Ptr = Max then
390          raise Bad_Switch;
391
392       else
393          Ptr := Ptr + 1;
394       end if;
395
396       --  A little check, "gnat" at the start of a switch is not allowed
397       --  except for the compiler (where it was already removed)
398
399       if Switch_Chars'Length >= Ptr + 3
400         and then Switch_Chars (Ptr .. Ptr + 3) = "gnat"
401       then
402          Osint.Fail
403            ("invalid switch: """, Switch_Chars, """ (gnat not needed here)");
404       end if;
405
406       --  Loop to scan through switches given in switch string
407
408       while Ptr <= Max loop
409          C := Switch_Chars (Ptr);
410
411          --  Processing for a switch
412
413          case C is
414
415          when 'a' =>
416             Ptr := Ptr + 1;
417             Check_Readonly_Files := True;
418
419          --  Processing for b switch
420
421          when 'b' =>
422             Ptr := Ptr + 1;
423             Bind_Only := True;
424
425          --  Processing for c switch
426
427          when 'c' =>
428             Ptr := Ptr + 1;
429             Compile_Only := True;
430
431          --  Processing for C switch
432
433          when 'C' =>
434             Ptr := Ptr + 1;
435             Create_Mapping_File := True;
436
437          --  Processing for d switch
438
439          when 'd' =>
440
441             --  Note: for the debug switch, the remaining characters in this
442             --  switch field must all be debug flags, since all valid switch
443             --  characters are also valid debug characters. This switch is not
444             --  documented on purpose because it is only used by the
445             --  implementors.
446
447             --  Loop to scan out debug flags
448
449             while Ptr < Max loop
450                Ptr := Ptr + 1;
451                C := Switch_Chars (Ptr);
452                exit when C = ASCII.NUL or else C = '/' or else C = '-';
453
454                if C in '1' .. '9' or else
455                   C in 'a' .. 'z' or else
456                   C in 'A' .. 'Z'
457                then
458                   Set_Debug_Flag (C);
459                else
460                   raise Bad_Switch;
461                end if;
462             end loop;
463
464             --  Make sure Zero_Cost_Exceptions is set if gnatdX set. This
465             --  is for backwards compatibility with old versions and usage.
466
467             if Debug_Flag_XX then
468                Zero_Cost_Exceptions_Set := True;
469                Zero_Cost_Exceptions_Val := True;
470             end if;
471
472             return;
473
474          --  Processing for f switch
475
476          when 'f' =>
477             Ptr := Ptr + 1;
478             Force_Compilations := True;
479
480          --  Processing for h switch
481
482          when 'h' =>
483             Ptr := Ptr + 1;
484             Usage_Requested := True;
485
486          --  Processing for i switch
487
488          when 'i' =>
489             Ptr := Ptr + 1;
490             In_Place_Mode := True;
491
492          --  Processing for j switch
493
494          when 'j' =>
495             Ptr := Ptr + 1;
496
497             declare
498                Max_Proc : Pos;
499             begin
500                Scan_Pos (Switch_Chars, Max, Ptr, Max_Proc);
501                Maximum_Processes := Positive (Max_Proc);
502             end;
503
504          --  Processing for k switch
505
506          when 'k' =>
507             Ptr := Ptr + 1;
508             Keep_Going := True;
509
510          --  Processing for l switch
511
512          when 'l' =>
513             Ptr := Ptr + 1;
514             Link_Only := True;
515
516          when 'M' =>
517             Ptr := Ptr + 1;
518             List_Dependencies := True;
519
520          --  Processing for n switch
521
522          when 'n' =>
523             Ptr := Ptr + 1;
524             Do_Not_Execute := True;
525
526          --  Processing for o switch
527
528          when 'o' =>
529             Ptr := Ptr + 1;
530
531             if Output_File_Name_Present then
532                raise Too_Many_Output_Files;
533             else
534                Output_File_Name_Present := True;
535             end if;
536
537          --  Processing for q switch
538
539          when 'q' =>
540             Ptr := Ptr + 1;
541             Quiet_Output := True;
542
543          --  Processing for s switch
544
545          when 's' =>
546             Ptr := Ptr + 1;
547             Check_Switches := True;
548
549          --  Processing for v switch
550
551          when 'v' =>
552             Ptr := Ptr + 1;
553             Verbose_Mode := True;
554
555          --  Processing for z switch
556
557          when 'z' =>
558             Ptr := Ptr + 1;
559             No_Main_Subprogram := True;
560
561          --  Ignore extra switch character
562
563          when '/' | '-' =>
564             Ptr := Ptr + 1;
565
566          --  Anything else is an error (illegal switch character)
567
568          when others =>
569             raise Bad_Switch;
570
571          end case;
572       end loop;
573
574    exception
575       when Bad_Switch =>
576          Osint.Fail ("invalid switch: ", (1 => C));
577
578       when Bad_Switch_Value =>
579          Osint.Fail ("numeric value too big for switch: ", (1 => C));
580
581       when Missing_Switch_Value =>
582          Osint.Fail ("missing numeric value for switch: ", (1 => C));
583
584       when Too_Many_Output_Files =>
585          Osint.Fail ("duplicate -o switch");
586
587    end Scan_Make_Switches;
588
589 end Switch.M;