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-2013, 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
26with Debug;    use Debug;
27with Makeutl;  use Makeutl;
28with Osint;    use Osint;
29with Opt;      use Opt;
30with Prj;      use Prj;
31with Prj.Env;  use Prj.Env;
32with Table;
33
34with System.Multiprocessors; use System.Multiprocessors;
35
36package body Switch.M is
37
38   package Normalized_Switches is new Table.Table
39     (Table_Component_Type => String_Access,
40      Table_Index_Type     => Integer,
41      Table_Low_Bound      => 1,
42      Table_Initial        => 20,
43      Table_Increment      => 100,
44      Table_Name           => "Switch.M.Normalized_Switches");
45   --  This table is used to keep the normalized switches, so that they may be
46   --  reused for subsequent invocations of Normalize_Compiler_Switches with
47   --  similar switches.
48
49   Initial_Number_Of_Switches : constant := 10;
50
51   Global_Switches : Argument_List_Access := null;
52   --  Used by function Normalize_Compiler_Switches
53
54   ---------------------------------
55   -- Normalize_Compiler_Switches --
56   ---------------------------------
57
58   procedure Normalize_Compiler_Switches
59     (Switch_Chars : String;
60      Switches     : in out Argument_List_Access;
61      Last         : out Natural)
62   is
63      Switch_Starts_With_Gnat : Boolean;
64
65      Ptr : Integer := Switch_Chars'First;
66      Max : constant Integer := Switch_Chars'Last;
67      C   : Character := ' ';
68
69      Storing      : String := Switch_Chars;
70      First_Stored : Positive := Ptr + 1;
71      Last_Stored  : Positive := First_Stored;
72
73      procedure Add_Switch_Component (S : String);
74      --  Add a new String_Access component in Switches. If a string equal
75      --  to S is already stored in the table Normalized_Switches, use it.
76      --  Otherwise add a new component to the table.
77
78      --------------------------
79      -- Add_Switch_Component --
80      --------------------------
81
82      procedure Add_Switch_Component (S : String) is
83      begin
84         --  If Switches is null, allocate a new array
85
86         if Switches = null then
87            Switches := new Argument_List (1 .. Initial_Number_Of_Switches);
88
89         --  Otherwise, if Switches is full, extend it
90
91         elsif Last = Switches'Last then
92            declare
93               New_Switches : constant Argument_List_Access :=
94                                new Argument_List
95                                      (1 .. Switches'Length + Switches'Length);
96            begin
97               New_Switches (1 .. Switches'Length) := Switches.all;
98               Last := Switches'Length;
99               Switches := New_Switches;
100            end;
101         end if;
102
103         --  If this is the first switch, Last designates the first component
104
105         if Last = 0 then
106            Last := Switches'First;
107         else
108            Last := Last + 1;
109         end if;
110
111         --  Look into the table Normalized_Switches for a similar string.
112         --  If one is found, put it at the added component, and return.
113
114         for Index in 1 .. Normalized_Switches.Last loop
115            if S = Normalized_Switches.Table (Index).all then
116               Switches (Last) := Normalized_Switches.Table (Index);
117               return;
118            end if;
119         end loop;
120
121         --  No string equal to S was found in the table Normalized_Switches.
122         --  Add a new component in the table.
123
124         Switches (Last) := new String'(S);
125         Normalized_Switches.Append (Switches (Last));
126      end Add_Switch_Component;
127
128   --  Start of processing for Normalize_Compiler_Switches
129
130   begin
131      Last := 0;
132
133      if Ptr = Max or else Switch_Chars (Ptr) /= '-' then
134         return;
135      end if;
136
137      Ptr := Ptr + 1;
138
139      Switch_Starts_With_Gnat :=
140         Ptr + 3 <= Max and then Switch_Chars (Ptr .. Ptr + 3) = "gnat";
141
142      if Switch_Starts_With_Gnat then
143         Ptr := Ptr + 4;
144         First_Stored := Ptr;
145      end if;
146
147      while Ptr <= Max loop
148         C := Switch_Chars (Ptr);
149
150         --  Processing for a switch
151
152         case Switch_Starts_With_Gnat is
153
154            when False =>
155
156               --  All switches that don't start with -gnat stay as is,
157               --  except -pg, -Wall, -k8, -w
158
159               if Switch_Chars = "-pg" or else Switch_Chars = "-p" then
160
161                  --  The gcc driver converts -pg to -p, so that is what
162                  --  is stored in the ALI file.
163
164                  Add_Switch_Component ("-p");
165
166               elsif Switch_Chars = "-Wall" then
167
168                  --  The gcc driver adds -gnatwa when -Wall is used
169
170                  Add_Switch_Component ("-gnatwa");
171                  Add_Switch_Component ("-Wall");
172
173               elsif Switch_Chars = "-k8" then
174
175                  --  The gcc driver transforms -k8 into -gnatk8
176
177                  Add_Switch_Component ("-gnatk8");
178
179               elsif Switch_Chars = "-w" then
180
181                  --  The gcc driver adds -gnatws when -w is used
182
183                  Add_Switch_Component ("-gnatws");
184                  Add_Switch_Component ("-w");
185
186               elsif Switch_Chars'Length > 6
187                 and then
188                   Switch_Chars (Switch_Chars'First .. Switch_Chars'First + 5)
189                                                             = "--RTS="
190               then
191                  Add_Switch_Component (Switch_Chars);
192
193                  --  When --RTS=mtp is used, the gcc driver adds -mrtp
194
195                  if Switch_Chars = "--RTS=mtp" then
196                     Add_Switch_Component ("-mrtp");
197                  end if;
198
199               --  Switch for universal addressing on AAMP target
200
201               elsif Switch_Chars'Length >= 5
202                 and then
203                   Switch_Chars
204                     (Switch_Chars'First .. Switch_Chars'First + 4) = "-univ"
205               then
206                  Add_Switch_Component (Switch_Chars);
207
208               --  Switch for specifying AAMP target library
209
210               elsif Switch_Chars'Length > 13
211                 and then
212                   Switch_Chars (Switch_Chars'First .. Switch_Chars'First + 12)
213                     = "-aamp_target="
214               then
215                  Add_Switch_Component (Switch_Chars);
216
217               --  Special case for -fstack-check (alias for
218               --  -fstack-check=specific)
219
220               elsif Switch_Chars = "-fstack-check" then
221                  Add_Switch_Component ("-fstack-check=specific");
222
223               --  Take only into account switches that are transmitted to
224               --  gnat1 by the gcc driver and stored by gnat1 in the ALI file.
225
226               else
227                  case C is
228                     when 'O' | 'W' | 'w' | 'f' | 'd' | 'g' | 'm' =>
229                        Add_Switch_Component (Switch_Chars);
230
231                     when others =>
232                        null;
233                  end case;
234               end if;
235
236               return;
237
238            when True =>
239
240               case C is
241
242                  --  One-letter switches
243
244                  when 'a' | 'A' | 'b' | 'B' | 'c' | 'C' | 'E' | 'f' |
245                       'F' | 'g' | 'h' | 'H' | 'I' | 'L' | 'N' | 'p' |
246                       'P' | 'q' | 'Q' | 'r' | 's' | 'S' | 't' | 'u' |
247                       'U' | 'v' | 'x' | 'X' | 'Z' =>
248                     Storing (First_Stored) := C;
249                     Add_Switch_Component
250                       (Storing (Storing'First .. First_Stored));
251                     Ptr := Ptr + 1;
252
253                  --  One-letter switches followed by a positive number
254
255                  when 'D' | 'G' | 'j' | 'k' | 'm' | 'T' =>
256                     Storing (First_Stored) := C;
257                     Last_Stored := First_Stored;
258
259                     if Ptr <= Max and then Switch_Chars (Ptr) = '=' then
260                        Ptr := Ptr + 1;
261                     end if;
262
263                     loop
264                        Ptr := Ptr + 1;
265                        exit when Ptr > Max
266                          or else Switch_Chars (Ptr) not in '0' .. '9';
267                        Last_Stored := Last_Stored + 1;
268                        Storing (Last_Stored) := Switch_Chars (Ptr);
269                     end loop;
270
271                     Add_Switch_Component
272                       (Storing (Storing'First .. Last_Stored));
273
274                  when 'd' =>
275                     Storing (First_Stored) := 'd';
276
277                     while Ptr < Max loop
278                        Ptr := Ptr + 1;
279                        C := Switch_Chars (Ptr);
280                        exit when C = ASCII.NUL or else C = '/'
281                          or else C = '-';
282
283                        if C in '1' .. '9' or else
284                           C in 'a' .. 'z' or else
285                           C in 'A' .. 'Z'
286                        then
287                           Storing (First_Stored + 1) := C;
288                           Add_Switch_Component
289                             (Storing (Storing'First .. First_Stored + 1));
290
291                        else
292                           Last := 0;
293                           return;
294                        end if;
295                     end loop;
296
297                     return;
298
299                  when 'e' =>
300
301                     --  Some of the gnate... switches are not stored
302
303                     Storing (First_Stored) := 'e';
304                     Ptr := Ptr + 1;
305
306                     if Ptr > Max then
307                        Last := 0;
308                        return;
309
310                     else
311                        case Switch_Chars (Ptr) is
312
313                           when 'A' =>
314                              Ptr := Ptr + 1;
315                              Add_Switch_Component ("-gnateA");
316
317                           when 'D' =>
318                              Storing (First_Stored + 1 ..
319                                         First_Stored + Max - Ptr + 1) :=
320                                  Switch_Chars (Ptr .. Max);
321                              Add_Switch_Component
322                                (Storing (Storing'First ..
323                                   First_Stored + Max - Ptr + 1));
324                              Ptr := Max + 1;
325
326                           when 'E' | 'F' | 'G' | 'S' | 'u' | 'V' | 'Y' =>
327                              Add_Switch_Component
328                                ("-gnate" & Switch_Chars (Ptr));
329                              Ptr := Ptr + 1;
330
331                           when 'i' | 'I' =>
332                              declare
333                                 First : constant Positive := Ptr;
334
335                              begin
336                                 Ptr := Ptr + 1;
337
338                                 if Ptr <= Max and then
339                                   Switch_Chars (Ptr) = '='
340                                 then
341                                    Ptr := Ptr + 1;
342                                 end if;
343
344                                 while Ptr <= Max and then
345                                       Switch_Chars (Ptr) in '0' .. '9'
346                                 loop
347                                    Ptr := Ptr + 1;
348                                 end loop;
349
350                                 Storing (First_Stored + 1 ..
351                                            First_Stored + Ptr - First) :=
352                                     Switch_Chars (First .. Ptr - 1);
353                                 Add_Switch_Component
354                                   (Storing (Storing'First ..
355                                      First_Stored + Ptr - First));
356                              end;
357
358                           when 'l' =>
359                              Ptr := Ptr + 1;
360                              Add_Switch_Component ("-gnatel");
361
362                           when 'L' =>
363                              Ptr := Ptr + 1;
364                              Add_Switch_Component ("-gnateL");
365
366                           when 'p' =>
367                              Ptr := Ptr + 1;
368
369                              if Ptr = Max then
370                                 Last := 0;
371                                 return;
372                              end if;
373
374                              if Switch_Chars (Ptr) = '=' then
375                                 Ptr := Ptr + 1;
376                              end if;
377
378                                 --  To normalize, always put a '=' after
379                                 --  -gnatep. Because that could lengthen the
380                                 --  switch string, declare a local variable.
381
382                              declare
383                                 To_Store : String (1 .. Max - Ptr + 9);
384                              begin
385                                 To_Store (1 .. 8) := "-gnatep=";
386                                 To_Store (9 .. Max - Ptr + 9) :=
387                                   Switch_Chars (Ptr .. Max);
388                                 Add_Switch_Component (To_Store);
389                              end;
390
391                              return;
392
393                           when others =>
394                              Last := 0;
395                              return;
396                        end case;
397                     end if;
398
399                  when 'i' =>
400                     Storing (First_Stored) := 'i';
401
402                     Ptr := Ptr + 1;
403
404                     if Ptr > Max then
405                        Last := 0;
406                        return;
407                     end if;
408
409                     C := Switch_Chars (Ptr);
410
411                     if C in '1' .. '5'
412                       or else C = '8'
413                       or else C = 'p'
414                       or else C = 'f'
415                       or else C = 'n'
416                       or else C = 'w'
417                     then
418                        Storing (First_Stored + 1) := C;
419                        Add_Switch_Component
420                          (Storing (Storing'First .. First_Stored + 1));
421                        Ptr := Ptr + 1;
422
423                     else
424                        Last := 0;
425                        return;
426                     end if;
427
428                  --  -gnatl may be -gnatl=<file name>
429
430                  when 'l' =>
431                     Ptr := Ptr + 1;
432
433                     if Ptr > Max or else Switch_Chars (Ptr) /= '=' then
434                        Add_Switch_Component ("-gnatl");
435
436                     else
437                        Add_Switch_Component
438                          ("-gnatl" & Switch_Chars (Ptr .. Max));
439                        return;
440                     end if;
441
442                  --  -gnatn may be -gnatn, -gnatn1, or -gnatn2
443
444                  when 'n' =>
445                     Last_Stored := First_Stored;
446                     Storing (Last_Stored) := 'n';
447                     Ptr := Ptr + 1;
448
449                     if Ptr <= Max
450                       and then Switch_Chars (Ptr) in '1' .. '2'
451                     then
452                        Last_Stored := Last_Stored + 1;
453                        Storing (Last_Stored) := Switch_Chars (Ptr);
454                        Ptr := Ptr + 1;
455                     end if;
456
457                     Add_Switch_Component
458                       (Storing (Storing'First .. Last_Stored));
459
460                  --  -gnato may be -gnatox or -gnatoxx, with x=0/1/2/3
461
462                  when 'o' =>
463                     Last_Stored := First_Stored;
464                     Storing (Last_Stored) := 'o';
465                     Ptr := Ptr + 1;
466
467                     if Ptr <= Max
468                       and then Switch_Chars (Ptr) in '0' .. '3'
469                     then
470                        Last_Stored := Last_Stored + 1;
471                        Storing (Last_Stored) := Switch_Chars (Ptr);
472                        Ptr := Ptr + 1;
473
474                        if Ptr <= Max
475                          and then Switch_Chars (Ptr) in '0' .. '3'
476                        then
477                           Last_Stored := Last_Stored + 1;
478                           Storing (Last_Stored) := Switch_Chars (Ptr);
479                           Ptr := Ptr + 1;
480                        end if;
481                     end if;
482
483                     Add_Switch_Component
484                       (Storing (Storing'First .. Last_Stored));
485
486                  --  -gnatR may be followed by '0', '1', '2' or '3',
487                  --  then by 's'
488
489                  when 'R' =>
490                     Last_Stored := First_Stored;
491                     Storing (Last_Stored) := 'R';
492                     Ptr := Ptr + 1;
493
494                     if Ptr <= Max
495                       and then Switch_Chars (Ptr) in '0' .. '9'
496                     then
497                        C := Switch_Chars (Ptr);
498
499                        if C in '4' .. '9' then
500                           Last := 0;
501                           return;
502
503                        else
504                           Last_Stored := Last_Stored + 1;
505                           Storing (Last_Stored) := C;
506                           Ptr := Ptr + 1;
507
508                           if Ptr <= Max
509                             and then Switch_Chars (Ptr) = 's'
510                           then
511                              Last_Stored := Last_Stored + 1;
512                              Storing (Last_Stored) := 's';
513                              Ptr := Ptr + 1;
514                           end if;
515                        end if;
516                     end if;
517
518                     Add_Switch_Component
519                       (Storing (Storing'First .. Last_Stored));
520
521                  --  -gnatWx, x = 'h'. 'u', 's', 'e', '8' or 'b'
522
523                  when 'W' =>
524                     Storing (First_Stored) := 'W';
525                     Ptr := Ptr + 1;
526
527                     if Ptr <= Max then
528                        case Switch_Chars (Ptr) is
529                           when 'h' | 'u' | 's' | 'e' | '8' | 'b' =>
530                              Storing (First_Stored + 1) := Switch_Chars (Ptr);
531                              Add_Switch_Component
532                                (Storing (Storing'First .. First_Stored + 1));
533                              Ptr := Ptr + 1;
534
535                           when others =>
536                              Last := 0;
537                              return;
538                        end case;
539                     end if;
540
541                  --  Multiple switches
542
543                  when 'V' | 'w' | 'y' =>
544                     Storing (First_Stored) := C;
545                     Ptr := Ptr + 1;
546
547                     if Ptr > Max then
548                        if C = 'y' then
549                           Add_Switch_Component
550                             (Storing (Storing'First .. First_Stored));
551
552                        else
553                           Last := 0;
554                           return;
555                        end if;
556                     end if;
557
558                     --  Loop through remaining switch characters in string
559
560                     while Ptr <= Max loop
561                        C := Switch_Chars (Ptr);
562                        Ptr := Ptr + 1;
563
564                        --  -gnatyMxxx
565
566                        if C = 'M' and then Storing (First_Stored) = 'y' then
567                           Last_Stored := First_Stored + 1;
568                           Storing (Last_Stored) := 'M';
569                           while Ptr <= Max loop
570                              C := Switch_Chars (Ptr);
571                              exit when C not in '0' .. '9';
572                              Last_Stored := Last_Stored + 1;
573                              Storing (Last_Stored) := C;
574                              Ptr := Ptr + 1;
575                           end loop;
576
577                           --  If there is no digit after -gnatyM,
578                           --  the switch is invalid.
579
580                           if Last_Stored = First_Stored + 1 then
581                              Last := 0;
582                              return;
583
584                           else
585                              Add_Switch_Component
586                                (Storing (Storing'First .. Last_Stored));
587                           end if;
588
589                        --  --gnatx.x
590
591                        elsif C = '.' and then Ptr <= Max then
592                           Storing (First_Stored + 1) := '.';
593                           Storing (First_Stored + 2) := Switch_Chars (Ptr);
594                           Ptr := Ptr + 1;
595                           Add_Switch_Component
596                             (Storing (Storing'First .. First_Stored + 2));
597
598                        --  All other switches are -gnatxx
599
600                        else
601                           Storing (First_Stored + 1) := C;
602                           Add_Switch_Component
603                             (Storing (Storing'First .. First_Stored + 1));
604                        end if;
605                     end loop;
606
607                  --  -gnat95 -gnat05
608
609                  when '0' | '9' =>
610                     Last_Stored := First_Stored;
611                     Storing (Last_Stored) := C;
612                     Ptr := Ptr + 1;
613
614                     if Ptr /= Max or else Switch_Chars (Ptr) /= '5' then
615
616                        --  Invalid switch
617
618                        Last := 0;
619                        return;
620
621                     else
622                        Last_Stored := Last_Stored + 1;
623                        Storing (Last_Stored) := '5';
624                        Add_Switch_Component
625                          (Storing (Storing'First .. Last_Stored));
626                        Ptr := Ptr + 1;
627                     end if;
628
629                     --  -gnat12
630
631                  when '1' =>
632                     Last_Stored := First_Stored;
633                     Storing (Last_Stored) := C;
634                     Ptr := Ptr + 1;
635
636                     if Ptr /= Max or else Switch_Chars (Ptr) /= '2' then
637
638                        --  Invalid switch
639
640                        Last := 0;
641                        return;
642
643                     else
644                        Last_Stored := Last_Stored + 1;
645                        Storing (Last_Stored) := '2';
646                        Add_Switch_Component
647                          (Storing (Storing'First .. Last_Stored));
648                        Ptr := Ptr + 1;
649                     end if;
650
651                     --  -gnat2005 -gnat2012
652
653                  when '2' =>
654                     if Ptr + 3 /= Max then
655                        Last := 0;
656                        return;
657
658                     elsif Switch_Chars (Ptr + 1 .. Ptr + 3) = "005" then
659                        Last_Stored := First_Stored + 3;
660                        Storing (First_Stored .. Last_Stored) := "2005";
661                        Add_Switch_Component
662                          (Storing (Storing'First .. Last_Stored));
663                        Ptr := Max + 1;
664
665                     elsif Switch_Chars (Ptr + 1 .. Ptr + 3) = "012" then
666                        Last_Stored := First_Stored + 3;
667                        Storing (First_Stored .. Last_Stored) := "2012";
668                        Add_Switch_Component
669                          (Storing (Storing'First .. Last_Stored));
670                        Ptr := Max + 1;
671
672                     else
673
674                        --  Invalid switch
675
676                        Last := 0;
677                        return;
678
679                     end if;
680
681                  --  -gnat83
682
683                  when '8' =>
684                     Last_Stored := First_Stored;
685                     Storing (Last_Stored) := '8';
686                     Ptr := Ptr + 1;
687
688                     if Ptr /= Max or else Switch_Chars (Ptr) /= '3' then
689
690                        --  Invalid switch
691
692                        Last := 0;
693                        return;
694
695                     else
696                        Last_Stored := Last_Stored + 1;
697                        Storing (Last_Stored) := '3';
698                        Add_Switch_Component
699                          (Storing (Storing'First .. Last_Stored));
700                        Ptr := Ptr + 1;
701                     end if;
702
703                  --  Not a valid switch
704
705                  when others =>
706                     Last := 0;
707                     return;
708
709               end case;
710
711         end case;
712      end loop;
713   end Normalize_Compiler_Switches;
714
715   function Normalize_Compiler_Switches
716     (Switch_Chars : String) return Argument_List
717   is
718      Last : Natural;
719
720   begin
721      Normalize_Compiler_Switches (Switch_Chars, Global_Switches, Last);
722
723      if Last = 0 then
724         return (1 .. 0 => null);
725      else
726         return Global_Switches (Global_Switches'First .. Last);
727      end if;
728   end Normalize_Compiler_Switches;
729
730   ------------------------
731   -- Scan_Make_Switches --
732   ------------------------
733
734   procedure Scan_Make_Switches
735     (Env               : in out Prj.Tree.Environment;
736      Switch_Chars      : String;
737      Success           : out Boolean)
738   is
739      Ptr : Integer          := Switch_Chars'First;
740      Max : constant Integer := Switch_Chars'Last;
741      C   : Character        := ' ';
742
743   begin
744      --  Assume a good switch
745
746      Success := True;
747
748      --  Skip past the initial character (must be the switch character)
749
750      if Ptr = Max then
751         Bad_Switch (Switch_Chars);
752
753      else
754         Ptr := Ptr + 1;
755      end if;
756
757      --  A little check, "gnat" at the start of a switch is for the compiler
758
759      if Switch_Chars'Length >= Ptr + 3
760        and then Switch_Chars (Ptr .. Ptr + 3) = "gnat"
761      then
762         Success := False;
763         return;
764      end if;
765
766      C := Switch_Chars (Ptr);
767
768      --  Multiple character switches
769
770      if Switch_Chars'Length > 2 then
771         if Switch_Chars = "--create-missing-dirs" then
772            Setup_Projects := True;
773
774         elsif Switch_Chars'Length > Subdirs_Option'Length
775           and then
776             Switch_Chars
777               (Switch_Chars'First ..
778                Switch_Chars'First + Subdirs_Option'Length - 1) =
779                                                            Subdirs_Option
780         then
781            Subdirs :=
782              new String'
783                (Switch_Chars
784                  (Switch_Chars'First + Subdirs_Option'Length ..
785                   Switch_Chars'Last));
786
787         elsif Switch_Chars = Makeutl.Unchecked_Shared_Lib_Imports then
788            Opt.Unchecked_Shared_Lib_Imports := True;
789
790         elsif Switch_Chars = Makeutl.Single_Compile_Per_Obj_Dir_Switch then
791            Opt.One_Compilation_Per_Obj_Dir := True;
792
793         elsif Switch_Chars (Ptr) = '-' then
794            Bad_Switch (Switch_Chars);
795
796         elsif Switch_Chars'Length > 3
797           and then Switch_Chars (Ptr .. Ptr + 1) = "aP"
798         then
799            Add_Directories
800              (Env.Project_Path,
801               Switch_Chars (Ptr + 2 .. Switch_Chars'Last));
802
803         elsif C = 'v' and then Switch_Chars'Length = 3 then
804            Ptr := Ptr + 1;
805            Verbose_Mode := True;
806
807            case Switch_Chars (Ptr) is
808               when 'l' =>
809                  Verbosity_Level := Opt.Low;
810
811               when 'm' =>
812                  Verbosity_Level := Opt.Medium;
813
814               when 'h' =>
815                  Verbosity_Level := Opt.High;
816
817               when others =>
818                  Success := False;
819            end case;
820
821         elsif C = 'd' then
822
823            --  Note: for the debug switch, the remaining characters in this
824            --  switch field must all be debug flags, since all valid switch
825            --  characters are also valid debug characters. This switch is not
826            --  documented on purpose because it is only used by the
827            --  implementors.
828
829            --  Loop to scan out debug flags
830
831            while Ptr < Max loop
832               Ptr := Ptr + 1;
833               C := Switch_Chars (Ptr);
834
835               if C in 'a' .. 'z' or else C in 'A' .. 'Z' then
836                  Set_Debug_Flag (C);
837               else
838                  Bad_Switch (Switch_Chars);
839               end if;
840            end loop;
841
842         elsif C = 'e' then
843            Ptr := Ptr + 1;
844
845            case Switch_Chars (Ptr) is
846
847               --  Processing for eI switch
848
849               when 'I' =>
850                  Ptr := Ptr + 1;
851                  Scan_Pos (Switch_Chars, Max, Ptr, Main_Index, C);
852
853                  if Ptr <= Max then
854                     Bad_Switch (Switch_Chars);
855                  end if;
856
857               --  Processing for eL switch
858
859               when 'L' =>
860                  if Ptr /= Max then
861                     Bad_Switch (Switch_Chars);
862
863                  else
864                     Follow_Links_For_Files := True;
865                     Follow_Links_For_Dirs  := True;
866                  end if;
867
868               --  Processing for eS switch
869
870               when 'S' =>
871                  if Ptr /= Max then
872                     Bad_Switch (Switch_Chars);
873
874                  else
875                     Commands_To_Stdout := True;
876                  end if;
877
878               when others =>
879                  Bad_Switch (Switch_Chars);
880            end case;
881
882         elsif C = 'j' then
883            Ptr := Ptr + 1;
884
885            declare
886               Max_Proc : Nat;
887
888            begin
889               Scan_Nat (Switch_Chars, Max, Ptr, Max_Proc, C);
890
891               if Ptr <= Max then
892                  Bad_Switch (Switch_Chars);
893
894               else
895                  if Max_Proc = 0 then
896                     Max_Proc := Nat (Number_Of_CPUs);
897
898                     if Max_Proc = 0 then
899                        Max_Proc := 1;
900                     end if;
901                  end if;
902
903                  Maximum_Processes := Positive (Max_Proc);
904               end if;
905            end;
906
907         elsif C = 'w' and then Switch_Chars'Length = 3 then
908            Ptr := Ptr + 1;
909
910            if Switch_Chars = "-we" then
911               Warning_Mode := Treat_As_Error;
912
913            elsif Switch_Chars = "-wn" then
914               Warning_Mode := Normal;
915
916            elsif Switch_Chars = "-ws" then
917               Warning_Mode  := Suppress;
918
919            else
920               Success := False;
921            end if;
922
923         else
924            Success := False;
925         end if;
926
927      --  Single-character switches
928
929      else
930         Check_Switch : begin
931
932            case C is
933
934               when 'a' =>
935                  Check_Readonly_Files := True;
936
937               --  Processing for b switch
938
939               when 'b' =>
940                  Bind_Only  := True;
941                  Make_Steps := True;
942
943               --  Processing for B switch
944
945               when 'B' =>
946                  Build_Bind_And_Link_Full_Project := True;
947
948               --  Processing for c switch
949
950               when 'c' =>
951                  Compile_Only := True;
952                  Make_Steps   := True;
953
954               --  Processing for C switch
955
956               when 'C' =>
957                  Opt.Create_Mapping_File := True;
958
959               --  Processing for D switch
960
961               when 'D' =>
962                  if Object_Directory_Present then
963                     Osint.Fail ("duplicate -D switch");
964
965                  else
966                     Object_Directory_Present := True;
967                  end if;
968
969               --  Processing for f switch
970
971               when 'f' =>
972                  Force_Compilations := True;
973
974               --  Processing for F switch
975
976               when 'F' =>
977                  Full_Path_Name_For_Brief_Errors := True;
978
979               --  Processing for h switch
980
981               when 'h' =>
982                  Usage_Requested := True;
983
984               --  Processing for i switch
985
986               when 'i' =>
987                  In_Place_Mode := True;
988
989               --  Processing for j switch
990
991               when 'j' =>
992                  --  -j not followed by a number is an error
993
994                  Bad_Switch (Switch_Chars);
995
996               --  Processing for k switch
997
998               when 'k' =>
999                  Keep_Going := True;
1000
1001               --  Processing for l switch
1002
1003               when 'l' =>
1004                  Link_Only  := True;
1005                  Make_Steps := True;
1006
1007               --  Processing for M switch
1008
1009               when 'M' =>
1010                  List_Dependencies := True;
1011
1012               --  Processing for n switch
1013
1014               when 'n' =>
1015                  Do_Not_Execute := True;
1016
1017               --  Processing for o switch
1018
1019               when 'o' =>
1020                  if Output_File_Name_Present then
1021                     Osint.Fail ("duplicate -o switch");
1022                  else
1023                     Output_File_Name_Present := True;
1024                  end if;
1025
1026               --  Processing for p switch
1027
1028               when 'p' =>
1029                  Setup_Projects := True;
1030
1031               --  Processing for q switch
1032
1033               when 'q' =>
1034                  Quiet_Output := True;
1035
1036               --  Processing for R switch
1037
1038               when 'R' =>
1039                  Run_Path_Option := False;
1040
1041               --  Processing for s switch
1042
1043               when 's' =>
1044                  Ptr := Ptr + 1;
1045                  Check_Switches := True;
1046
1047               --  Processing for v switch
1048
1049               when 'v' =>
1050                  Verbose_Mode := True;
1051                  Verbosity_Level := Opt.High;
1052
1053                  --  Processing for x switch
1054
1055               when 'x' =>
1056                  External_Unit_Compilation_Allowed := True;
1057                  Use_Include_Path_File := True;
1058
1059                  --  Processing for z switch
1060
1061               when 'z' =>
1062                  No_Main_Subprogram := True;
1063
1064                  --  Any other small letter is an illegal switch
1065
1066               when others =>
1067                  if C in 'a' .. 'z' then
1068                     Bad_Switch (Switch_Chars);
1069
1070                  else
1071                     Success := False;
1072                  end if;
1073
1074            end case;
1075         end Check_Switch;
1076      end if;
1077   end Scan_Make_Switches;
1078
1079end Switch.M;
1080