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