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