File : switch-b.adb


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                         GNAT COMPILER COMPONENTS                         --
   4 --                                                                          --
   5 --                             S W I T C H - B                              --
   6 --                                                                          --
   7 --                                 B o d y                                  --
   8 --                                                                          --
   9 --          Copyright (C) 2001-2015, 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 
  26 with Bindgen;
  27 with Debug;  use Debug;
  28 with Osint;  use Osint;
  29 with Opt;    use Opt;
  30 
  31 with System.WCh_Con; use System.WCh_Con;
  32 
  33 package body Switch.B is
  34 
  35    --------------------------
  36    -- Scan_Binder_Switches --
  37    --------------------------
  38 
  39    procedure Scan_Binder_Switches (Switch_Chars : String) is
  40       Max : constant Integer := Switch_Chars'Last;
  41       Ptr : Integer          := Switch_Chars'First;
  42       C   : Character        := ' ';
  43 
  44       function Get_Optional_Filename return String_Ptr;
  45       --  If current character is '=', return a newly allocated string that
  46       --  contains the remainder of the current switch (after the '='), else
  47       --  return null.
  48 
  49       function Get_Stack_Size (S : Character) return Int;
  50       --  Used for -d and -D to scan stack size including handling k/m. S is
  51       --  set to 'd' or 'D' to indicate the switch being scanned.
  52 
  53       ---------------------------
  54       -- Get_Optional_Filename --
  55       ---------------------------
  56 
  57       function Get_Optional_Filename return String_Ptr is
  58          Result : String_Ptr;
  59 
  60       begin
  61          if Ptr <= Max and then Switch_Chars (Ptr) = '=' then
  62             if Ptr = Max then
  63                Bad_Switch (Switch_Chars);
  64             else
  65                Result := new String'(Switch_Chars (Ptr + 1 .. Max));
  66                Ptr := Max + 1;
  67                return Result;
  68             end if;
  69          end if;
  70 
  71          return null;
  72       end Get_Optional_Filename;
  73 
  74       --------------------
  75       -- Get_Stack_Size --
  76       --------------------
  77 
  78       function Get_Stack_Size (S : Character) return Int is
  79          Result : Int;
  80 
  81       begin
  82          Scan_Pos (Switch_Chars, Max, Ptr, Result, S);
  83 
  84          --  In the following code, we enable overflow checking since the
  85          --  multiplication by K or M may cause overflow, which is an error.
  86 
  87          declare
  88             pragma Unsuppress (Overflow_Check);
  89 
  90          begin
  91             --  Check for additional character 'k' (for kilobytes) or 'm' (for
  92             --  Megabytes), but only if we have not reached the end of the
  93             --  switch string. Note that if this appears before the end of the
  94             --  string we will get an error when we test to make sure that the
  95             --  string is exhausted (at the end of the case).
  96 
  97             if Ptr <= Max then
  98                if Switch_Chars (Ptr) = 'k' then
  99                   Result := Result * 1024;
 100                   Ptr := Ptr + 1;
 101 
 102                elsif Switch_Chars (Ptr) = 'm' then
 103                   Result := Result * (1024 * 1024);
 104                   Ptr := Ptr + 1;
 105                end if;
 106             end if;
 107 
 108          exception
 109             when Constraint_Error =>
 110                Osint.Fail ("numeric value out of range for switch: " & S);
 111          end;
 112 
 113          return Result;
 114       end Get_Stack_Size;
 115 
 116    --  Start of processing for Scan_Binder_Switches
 117 
 118    begin
 119       --  Skip past the initial character (must be the switch character)
 120 
 121       if Ptr = Max then
 122          Bad_Switch (Switch_Chars);
 123       else
 124          Ptr := Ptr + 1;
 125       end if;
 126 
 127       --  A little check, "gnat" at the start of a switch is not allowed except
 128       --  for the compiler
 129 
 130       if Max >= Ptr + 3
 131         and then Switch_Chars (Ptr .. Ptr + 3) = "gnat"
 132       then
 133          Osint.Fail ("invalid switch: """ & Switch_Chars & """"
 134                      & " (gnat not needed here)");
 135       end if;
 136 
 137       --  Loop to scan through switches given in switch string
 138 
 139       Check_Switch : begin
 140          C := Switch_Chars (Ptr);
 141 
 142          case C is
 143 
 144          --  Processing for a switch
 145 
 146          when 'a' =>
 147             Ptr := Ptr + 1;
 148             Use_Pragma_Linker_Constructor := True;
 149 
 150          --  Processing for A switch
 151 
 152          when 'A' =>
 153             Ptr := Ptr + 1;
 154             Output_ALI_List := True;
 155             ALI_List_Filename := Get_Optional_Filename;
 156 
 157          --  Processing for b switch
 158 
 159          when 'b' =>
 160             Ptr := Ptr + 1;
 161             Brief_Output := True;
 162 
 163          --  Processing for c switch
 164 
 165          when 'c' =>
 166             Ptr := Ptr + 1;
 167             Check_Only := True;
 168 
 169          --  Processing for d switch
 170 
 171          when 'd' =>
 172 
 173             if Ptr = Max then
 174                Bad_Switch (Switch_Chars);
 175             end if;
 176 
 177             Ptr := Ptr + 1;
 178             C := Switch_Chars (Ptr);
 179 
 180             --  Case where character after -d is a digit (default stack size)
 181 
 182             if C in '0' .. '9' then
 183 
 184                --  In this case, we process the default primary stack size
 185 
 186                Default_Stack_Size := Get_Stack_Size ('d');
 187 
 188             --  Case where character after -d is not digit (debug flags)
 189 
 190             else
 191                --  Note: for the debug switch, the remaining characters in this
 192                --  switch field must all be debug flags, since all valid switch
 193                --  characters are also valid debug characters. This switch is
 194                --  not documented on purpose because it is only used by the
 195                --  implementors.
 196 
 197                --  Loop to scan out debug flags
 198 
 199                loop
 200                   C := Switch_Chars (Ptr);
 201 
 202                   if C in 'a' .. 'z' or else C in 'A' .. 'Z' then
 203                      Set_Debug_Flag (C);
 204                   else
 205                      Bad_Switch (Switch_Chars);
 206                   end if;
 207 
 208                   Ptr := Ptr + 1;
 209                   exit when Ptr > Max;
 210                end loop;
 211             end if;
 212 
 213          --  Processing for D switch
 214 
 215          when 'D' =>
 216             if Ptr = Max then
 217                Bad_Switch (Switch_Chars);
 218             end if;
 219 
 220             Ptr := Ptr + 1;
 221             Default_Sec_Stack_Size := Get_Stack_Size ('D');
 222 
 223          --  Processing for e switch
 224 
 225          when 'e' =>
 226             Ptr := Ptr + 1;
 227             Elab_Dependency_Output := True;
 228 
 229          --  Processing for E switch
 230 
 231          when 'E' =>
 232 
 233             --  -E is equivalent to -Ea (see below)
 234 
 235             Exception_Tracebacks := True;
 236             Ptr := Ptr + 1;
 237 
 238             if Ptr <= Max then
 239                case Switch_Chars (Ptr) is
 240 
 241                   --  -Ea sets Exception_Tracebacks
 242 
 243                   when 'a' => null;
 244 
 245                   --  -Es sets both Exception_Tracebacks and
 246                   --  Exception_Tracebacks_Symbolic.
 247 
 248                   when 's' => Exception_Tracebacks_Symbolic := True;
 249                   when others => Bad_Switch (Switch_Chars);
 250                end case;
 251 
 252                Ptr := Ptr + 1;
 253             end if;
 254 
 255          --  Processing for F switch
 256 
 257          when 'F' =>
 258             Ptr := Ptr + 1;
 259             Force_Checking_Of_Elaboration_Flags := True;
 260 
 261          --  Processing for g switch
 262 
 263          when 'g' =>
 264             Ptr := Ptr + 1;
 265 
 266             if Ptr <= Max then
 267                C := Switch_Chars (Ptr);
 268 
 269                if C in '0' .. '3' then
 270                   Debugger_Level :=
 271                     Character'Pos
 272                       (Switch_Chars (Ptr)) - Character'Pos ('0');
 273                   Ptr := Ptr + 1;
 274                end if;
 275 
 276             else
 277                Debugger_Level := 2;
 278             end if;
 279 
 280          --  Processing for h switch
 281 
 282          when 'h' =>
 283             Ptr := Ptr + 1;
 284             Usage_Requested := True;
 285 
 286          --  Processing for i switch
 287 
 288          when 'i' =>
 289             if Ptr = Max then
 290                Bad_Switch (Switch_Chars);
 291             end if;
 292 
 293             Ptr := Ptr + 1;
 294             C := Switch_Chars (Ptr);
 295 
 296             if C in '1' .. '5'
 297               or else C = '8'
 298               or else C = 'p'
 299               or else C = 'f'
 300               or else C = 'n'
 301               or else C = 'w'
 302             then
 303                Identifier_Character_Set := C;
 304                Ptr := Ptr + 1;
 305             else
 306                Bad_Switch (Switch_Chars);
 307             end if;
 308 
 309          --  Processing for K switch
 310 
 311          when 'K' =>
 312             Ptr := Ptr + 1;
 313             Output_Linker_Option_List := True;
 314 
 315          --  Processing for l switch
 316 
 317          when 'l' =>
 318             Ptr := Ptr + 1;
 319             Elab_Order_Output := True;
 320 
 321          --  Processing for m switch
 322 
 323          when 'm' =>
 324             if Ptr = Max then
 325                Bad_Switch (Switch_Chars);
 326             end if;
 327 
 328             Ptr := Ptr + 1;
 329             Scan_Pos (Switch_Chars, Max, Ptr, Maximum_Messages, C);
 330 
 331          --  Processing for n switch
 332 
 333          when 'n' =>
 334             Ptr := Ptr + 1;
 335             Bind_Main_Program := False;
 336 
 337             --  Note: The -L option of the binder also implies -n, so
 338             --  any change here must also be reflected in the processing
 339             --  for -L that is found in Gnatbind.Scan_Bind_Arg.
 340 
 341          --  Processing for o switch
 342 
 343          when 'o' =>
 344             Ptr := Ptr + 1;
 345 
 346             if Output_File_Name_Present then
 347                Osint.Fail ("duplicate -o switch");
 348             else
 349                Output_File_Name_Present := True;
 350             end if;
 351 
 352          --  Processing for O switch
 353 
 354          when 'O' =>
 355             Ptr := Ptr + 1;
 356             Output_Object_List := True;
 357             Object_List_Filename := Get_Optional_Filename;
 358 
 359          --  Processing for p switch
 360 
 361          when 'p' =>
 362             Ptr := Ptr + 1;
 363             Pessimistic_Elab_Order := True;
 364 
 365          --  Processing for P switch
 366 
 367          when 'P' =>
 368             Ptr := Ptr + 1;
 369             CodePeer_Mode := True;
 370 
 371          --  Processing for q switch
 372 
 373          when 'q' =>
 374             Ptr := Ptr + 1;
 375             Quiet_Output := True;
 376 
 377          --  Processing for r switch
 378 
 379          when 'r' =>
 380             Ptr := Ptr + 1;
 381             List_Restrictions := True;
 382 
 383          --  Processing for R switch
 384 
 385          when 'R' =>
 386             Ptr := Ptr + 1;
 387             List_Closure := True;
 388 
 389             if Ptr <= Max and then Switch_Chars (Ptr) = 'a' then
 390                Ptr := Ptr + 1;
 391                List_Closure_All := True;
 392             end if;
 393 
 394          --  Processing for s switch
 395 
 396          when 's' =>
 397             Ptr := Ptr + 1;
 398             All_Sources := True;
 399             Check_Source_Files := True;
 400 
 401          --  Processing for t switch
 402 
 403          when 't' =>
 404             Ptr := Ptr + 1;
 405             Tolerate_Consistency_Errors := True;
 406 
 407          --  Processing for T switch
 408 
 409          when 'T' =>
 410             if Ptr = Max then
 411                Bad_Switch (Switch_Chars);
 412             end if;
 413 
 414             Ptr := Ptr + 1;
 415             Time_Slice_Set := True;
 416             Scan_Nat (Switch_Chars, Max, Ptr, Time_Slice_Value, C);
 417             Time_Slice_Value := Time_Slice_Value * 1_000;
 418 
 419          --  Processing for u switch
 420 
 421          when 'u' =>
 422             if Ptr = Max then
 423                Bad_Switch (Switch_Chars);
 424             end if;
 425 
 426             Ptr := Ptr + 1;
 427             Dynamic_Stack_Measurement := True;
 428             Scan_Nat
 429               (Switch_Chars,
 430                Max,
 431                Ptr,
 432                Dynamic_Stack_Measurement_Array_Size,
 433                C);
 434 
 435          --  Processing for v switch
 436 
 437          when 'v' =>
 438             Ptr := Ptr + 1;
 439             Verbose_Mode := True;
 440 
 441          --  Processing for V switch
 442 
 443          when 'V' =>
 444             declare
 445                Eq : Integer;
 446             begin
 447                Ptr := Ptr + 1;
 448                Eq := Ptr;
 449                while Eq <= Max and then Switch_Chars (Eq) /= '=' loop
 450                   Eq := Eq + 1;
 451                end loop;
 452                if Eq = Ptr or else Eq = Max then
 453                   Bad_Switch (Switch_Chars);
 454                end if;
 455                Bindgen.Set_Bind_Env
 456                  (Key   => Switch_Chars (Ptr .. Eq - 1),
 457                   Value => Switch_Chars (Eq + 1 .. Max));
 458                Ptr := Max + 1;
 459             end;
 460 
 461          --  Processing for w switch
 462 
 463          when 'w' =>
 464             if Ptr = Max then
 465                Bad_Switch (Switch_Chars);
 466             end if;
 467 
 468             --  For the binder we only allow suppress/error cases
 469 
 470             Ptr := Ptr + 1;
 471 
 472             case Switch_Chars (Ptr) is
 473                when 'e' =>
 474                   Warning_Mode := Treat_As_Error;
 475 
 476                when 's' =>
 477                   Warning_Mode := Suppress;
 478 
 479                when others =>
 480                   Bad_Switch (Switch_Chars);
 481             end case;
 482 
 483             Ptr := Ptr + 1;
 484 
 485          --  Processing for W switch
 486 
 487          when 'W' =>
 488             Ptr := Ptr + 1;
 489 
 490             if Ptr > Max then
 491                Bad_Switch (Switch_Chars);
 492             end if;
 493 
 494             begin
 495                Wide_Character_Encoding_Method :=
 496                  Get_WC_Encoding_Method (Switch_Chars (Ptr));
 497             exception
 498                when Constraint_Error =>
 499                   Bad_Switch (Switch_Chars);
 500             end;
 501 
 502             Wide_Character_Encoding_Method_Specified := True;
 503 
 504             Upper_Half_Encoding :=
 505               Wide_Character_Encoding_Method in WC_Upper_Half_Encoding_Method;
 506 
 507             Ptr := Ptr + 1;
 508 
 509          --  Processing for x switch
 510 
 511          when 'x' =>
 512             Ptr := Ptr + 1;
 513             All_Sources := False;
 514             Check_Source_Files := False;
 515 
 516          --  Processing for X switch
 517 
 518          when 'X' =>
 519             if Ptr = Max then
 520                Bad_Switch (Switch_Chars);
 521             end if;
 522 
 523             Ptr := Ptr + 1;
 524             Scan_Pos (Switch_Chars, Max, Ptr, Default_Exit_Status, C);
 525 
 526          --  Processing for y switch
 527 
 528          when 'y' =>
 529             Ptr := Ptr + 1;
 530             Leap_Seconds_Support := True;
 531 
 532          --  Processing for z switch
 533 
 534          when 'z' =>
 535             Ptr := Ptr + 1;
 536             No_Main_Subprogram := True;
 537 
 538          --  Processing for Z switch
 539 
 540          when 'Z' =>
 541             Ptr := Ptr + 1;
 542             Zero_Formatting := True;
 543 
 544          --  Processing for --RTS
 545 
 546          when '-' =>
 547 
 548             if Ptr + 4 <= Max and then
 549               Switch_Chars (Ptr + 1 .. Ptr + 3) = "RTS"
 550             then
 551                Ptr := Ptr + 4;
 552 
 553                if Switch_Chars (Ptr) /= '=' or else Ptr = Max then
 554                   Osint.Fail ("missing path for --RTS");
 555 
 556                else
 557                   --  Valid --RTS switch
 558 
 559                   Opt.No_Stdinc := True;
 560                   Opt.RTS_Switch := True;
 561 
 562                   declare
 563                      Src_Path_Name : constant String_Ptr :=
 564                                        Get_RTS_Search_Dir
 565                                          (Switch_Chars (Ptr + 1 .. Max),
 566                                           Include);
 567                      Lib_Path_Name : constant String_Ptr :=
 568                                        Get_RTS_Search_Dir
 569                                          (Switch_Chars (Ptr + 1 .. Max),
 570                                           Objects);
 571 
 572                   begin
 573                      if Src_Path_Name /= null and then
 574                        Lib_Path_Name /= null
 575                      then
 576                         --  Set the RTS_*_Path_Name variables, so that the
 577                         --  correct directories will be set when a subsequent
 578                         --  call Osint.Add_Default_Search_Dirs is made.
 579 
 580                         RTS_Src_Path_Name := Src_Path_Name;
 581                         RTS_Lib_Path_Name := Lib_Path_Name;
 582 
 583                         Ptr := Max + 1;
 584 
 585                      elsif Src_Path_Name = null
 586                        and then Lib_Path_Name = null
 587                      then
 588                         Osint.Fail
 589                           ("RTS path not valid: missing adainclude and "
 590                            & "adalib directories");
 591                      elsif Src_Path_Name = null then
 592                         Osint.Fail
 593                           ("RTS path not valid: missing adainclude directory");
 594                      elsif Lib_Path_Name = null then
 595                         Osint.Fail
 596                           ("RTS path not valid: missing adalib directory");
 597                      end if;
 598                   end;
 599                end if;
 600 
 601             else
 602                Bad_Switch (Switch_Chars);
 603             end if;
 604 
 605          --  Anything else is an error (illegal switch character)
 606 
 607          when others =>
 608             Bad_Switch (Switch_Chars);
 609          end case;
 610 
 611          if Ptr <= Max then
 612             Bad_Switch (Switch_Chars);
 613          end if;
 614       end Check_Switch;
 615    end Scan_Binder_Switches;
 616 
 617 end Switch.B;