* doc/install.texi (Prerequisites): New section documenting
[official-gcc.git] / gcc / ada / switch-m.adb
blobb04672b5ffc1f277b99048d53e04a416f40e54a5
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- S W I T C H - M --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2001-2002 Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
21 -- --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 -- --
25 ------------------------------------------------------------------------------
27 with Debug; use Debug;
28 with Osint; use Osint;
29 with Opt; use Opt;
30 with Table;
32 package body Switch.M is
34 package Normalized_Switches is new Table.Table
35 (Table_Component_Type => String_Access,
36 Table_Index_Type => Integer,
37 Table_Low_Bound => 1,
38 Table_Initial => 20,
39 Table_Increment => 100,
40 Table_Name => "Switch.C.Normalized_Switches");
41 -- This table is used to keep the normalized switches, so that they may be
42 -- reused for subsequent invocations of Normalize_Compiler_Switches with
43 -- similar switches.
45 Initial_Number_Of_Switches : constant := 10;
47 Global_Switches : Argument_List_Access := null;
48 -- Used by function Normalize_Compiler_Switches
50 ---------------------------------
51 -- Normalize_Compiler_Switches --
52 ---------------------------------
54 procedure Normalize_Compiler_Switches
55 (Switch_Chars : String;
56 Switches : in out Argument_List_Access;
57 Last : out Natural)
59 Switch_Starts_With_Gnat : Boolean;
61 Ptr : Integer := Switch_Chars'First;
62 Max : constant Integer := Switch_Chars'Last;
63 C : Character := ' ';
65 First_Char : Integer := Ptr;
66 Storing : String := Switch_Chars;
67 First_Stored : Positive := Ptr + 1;
68 Last_Stored : Positive := First_Stored;
70 procedure Add_Switch_Component (S : String);
71 -- Add a new String_Access component in Switches. If a string equal
72 -- to S is already stored in the table Normalized_Switches, use it.
73 -- Other wise add a new component to the table.
75 --------------------------
76 -- Add_Switch_Component --
77 --------------------------
79 procedure Add_Switch_Component (S : String) is
80 begin
81 -- If Switches is null, allocate a new array
83 if Switches = null then
84 Switches := new Argument_List (1 .. Initial_Number_Of_Switches);
86 -- otherwise, if Switches is full, extend it
88 elsif Last = Switches'Last then
89 declare
90 New_Switches : Argument_List_Access := new Argument_List
91 (1 .. Switches'Length + Switches'Length);
92 begin
93 New_Switches (1 .. Switches'Length) := Switches.all;
94 Last := Switches'Length;
95 Switches := New_Switches;
96 end;
97 end if;
99 -- If this is the first switch, Last designates the first component
100 if Last = 0 then
101 Last := Switches'First;
103 else
104 Last := Last + 1;
105 end if;
107 -- Look into the table Normalized_Switches for a similar string.
108 -- If one is found, put it at the added component, and return.
110 for Index in 1 .. Normalized_Switches.Last loop
111 if S = Normalized_Switches.Table (Index).all then
112 Switches (Last) := Normalized_Switches.Table (Index);
113 return;
114 end if;
115 end loop;
117 -- No string equal to S was found in the table Normalized_Switches.
118 -- Add a new component in the table.
120 Switches (Last) := new String'(S);
121 Normalized_Switches.Increment_Last;
122 Normalized_Switches.Table (Normalized_Switches.Last) :=
123 Switches (Last);
124 end Add_Switch_Component;
126 -- Start of processing for Normalize_Compiler_Switches
128 begin
129 Last := 0;
131 if Ptr = Max or else Switch_Chars (Ptr) /= '-' then
132 return;
133 end if;
135 Ptr := Ptr + 1;
137 Switch_Starts_With_Gnat :=
138 Ptr + 3 <= Max and then Switch_Chars (Ptr .. Ptr + 3) = "gnat";
140 if Switch_Starts_With_Gnat then
141 Ptr := Ptr + 4;
142 First_Stored := Ptr;
143 end if;
145 while Ptr <= Max loop
146 First_Char := Ptr;
147 C := Switch_Chars (Ptr);
149 -- Processing for a switch
151 case Switch_Starts_With_Gnat is
153 when False =>
154 -- All switches that don't start with -gnat stay as is
156 Add_Switch_Component (Switch_Chars);
157 return;
159 when True =>
161 case C is
163 -- One-letter switches
165 when 'a' | 'A' | 'b' | 'c' | 'C' | 'D' | 'E' | 'f' |
166 'F' | 'g' | 'h' | 'H' | 'k' | 'l' | 'L' | 'n' | 'N' |
167 'o' | 'O' | 'p' | 'P' | 'q' | 'Q' | 'r' | 's' | 't' |
168 'u' | 'U' | 'v' | 'x' | 'X' | 'Z' =>
169 Storing (First_Stored) := C;
170 Add_Switch_Component
171 (Storing (Storing'First .. First_Stored));
172 Ptr := Ptr + 1;
174 -- One-letter switches followed by a positive number
176 when 'm' | 'T' =>
177 Storing (First_Stored) := C;
178 Last_Stored := First_Stored;
180 loop
181 Ptr := Ptr + 1;
182 exit when Ptr > Max
183 or else Switch_Chars (Ptr) not in '0' .. '9';
184 Last_Stored := Last_Stored + 1;
185 Storing (Last_Stored) := Switch_Chars (Ptr);
186 end loop;
188 Add_Switch_Component
189 (Storing (Storing'First .. Last_Stored));
191 when 'd' =>
192 Storing (First_Stored) := 'd';
194 while Ptr < Max loop
195 Ptr := Ptr + 1;
196 C := Switch_Chars (Ptr);
197 exit when C = ASCII.NUL or else C = '/'
198 or else C = '-';
200 if C in '1' .. '9' or else
201 C in 'a' .. 'z' or else
202 C in 'A' .. 'Z'
203 then
204 Storing (First_Stored + 1) := C;
205 Add_Switch_Component
206 (Storing (Storing'First .. First_Stored + 1));
208 else
209 Last := 0;
210 return;
211 end if;
212 end loop;
214 return;
216 when 'e' =>
217 -- None of the -gnate switches (-gnatec and -gnatem)
218 -- need to be store in an ALI file.
220 return;
222 when 'i' =>
223 Storing (First_Stored) := 'i';
225 Ptr := Ptr + 1;
227 if Ptr > Max then
228 Last := 0;
229 return;
230 end if;
232 C := Switch_Chars (Ptr);
234 if C in '1' .. '5'
235 or else C = '8'
236 or else C = 'p'
237 or else C = 'f'
238 or else C = 'n'
239 or else C = 'w'
240 then
241 Storing (First_Stored + 1) := C;
242 Add_Switch_Component
243 (Storing (Storing'First .. First_Stored + 1));
244 Ptr := Ptr + 1;
246 else
247 Last := 0;
248 return;
249 end if;
251 -- -gnatR may be followed by '0', '1', '2' or '3',
252 -- then by 's'
254 when 'R' =>
255 Last_Stored := First_Stored;
256 Storing (Last_Stored) := 'R';
257 Ptr := Ptr + 1;
259 if Ptr <= Max
260 and then Switch_Chars (Ptr) in '0' .. '9'
261 then
262 C := Switch_Chars (Ptr);
264 if C in '4' .. '9' then
265 Last := 0;
266 return;
268 else
269 Last_Stored := Last_Stored + 1;
270 Storing (Last_Stored) := C;
271 Ptr := Ptr + 1;
273 if Ptr <= Max
274 and then Switch_Chars (Ptr) = 's' then
275 Last_Stored := Last_Stored + 1;
276 Storing (Last_Stored) := 's';
277 Ptr := Ptr + 1;
278 end if;
279 end if;
280 end if;
282 Add_Switch_Component
283 (Storing (Storing'First .. Last_Stored));
285 -- Multiple switches
287 when 'V' | 'w' | 'y' =>
288 Storing (First_Stored) := C;
289 Ptr := Ptr + 1;
291 if Ptr > Max then
292 if C = 'y' then
293 Add_Switch_Component
294 (Storing (Storing'First .. First_Stored));
296 else
297 Last := 0;
298 return;
299 end if;
300 end if;
302 while Ptr <= Max loop
303 C := Switch_Chars (Ptr);
304 Ptr := Ptr + 1;
306 -- 'w' should be skipped in -gnatw
308 if C /= 'w' or else Storing (First_Stored) /= 'w' then
310 -- -gnatyMxxx
312 if C = 'M'
313 and then Storing (First_Stored) = 'y' then
314 Last_Stored := First_Stored + 1;
315 Storing (Last_Stored) := 'M';
317 while Ptr <= Max loop
318 C := Switch_Chars (Ptr);
319 exit when C not in '0' .. '9';
320 Last_Stored := Last_Stored + 1;
321 Storing (Last_Stored) := C;
322 Ptr := Ptr + 1;
323 end loop;
325 -- If there is no digit after -gnatyM,
326 -- the switch is invalid.
328 if Last_Stored = First_Stored + 1 then
329 Last := 0;
330 return;
332 else
333 Add_Switch_Component
334 (Storing (Storing'First .. Last_Stored));
335 end if;
337 -- All other switches are -gnatxx
339 else
340 Storing (First_Stored + 1) := C;
341 Add_Switch_Component
342 (Storing (Storing'First .. First_Stored + 1));
343 end if;
344 end if;
345 end loop;
347 -- Not a valid switch
349 when others =>
350 Last := 0;
351 return;
353 end case;
355 end case;
356 end loop;
357 end Normalize_Compiler_Switches;
359 function Normalize_Compiler_Switches
360 (Switch_Chars : String)
361 return Argument_List
363 Last : Natural;
365 begin
366 Normalize_Compiler_Switches (Switch_Chars, Global_Switches, Last);
368 if Last = 0 then
369 return (1 .. 0 => null);
371 else
372 return Global_Switches (Global_Switches'First .. Last);
373 end if;
375 end Normalize_Compiler_Switches;
377 ------------------------
378 -- Scan_Make_Switches --
379 ------------------------
381 procedure Scan_Make_Switches (Switch_Chars : String) is
382 Ptr : Integer := Switch_Chars'First;
383 Max : Integer := Switch_Chars'Last;
384 C : Character := ' ';
386 begin
387 -- Skip past the initial character (must be the switch character)
389 if Ptr = Max then
390 raise Bad_Switch;
392 else
393 Ptr := Ptr + 1;
394 end if;
396 -- A little check, "gnat" at the start of a switch is not allowed
397 -- except for the compiler (where it was already removed)
399 if Switch_Chars'Length >= Ptr + 3
400 and then Switch_Chars (Ptr .. Ptr + 3) = "gnat"
401 then
402 Osint.Fail
403 ("invalid switch: """, Switch_Chars, """ (gnat not needed here)");
404 end if;
406 -- Loop to scan through switches given in switch string
408 while Ptr <= Max loop
409 C := Switch_Chars (Ptr);
411 -- Processing for a switch
413 case C is
415 when 'a' =>
416 Ptr := Ptr + 1;
417 Check_Readonly_Files := True;
419 -- Processing for b switch
421 when 'b' =>
422 Ptr := Ptr + 1;
423 Bind_Only := True;
425 -- Processing for c switch
427 when 'c' =>
428 Ptr := Ptr + 1;
429 Compile_Only := True;
431 -- Processing for C switch
433 when 'C' =>
434 Ptr := Ptr + 1;
435 Create_Mapping_File := True;
437 -- Processing for d switch
439 when 'd' =>
441 -- Note: for the debug switch, the remaining characters in this
442 -- switch field must all be debug flags, since all valid switch
443 -- characters are also valid debug characters. This switch is not
444 -- documented on purpose because it is only used by the
445 -- implementors.
447 -- Loop to scan out debug flags
449 while Ptr < Max loop
450 Ptr := Ptr + 1;
451 C := Switch_Chars (Ptr);
452 exit when C = ASCII.NUL or else C = '/' or else C = '-';
454 if C in '1' .. '9' or else
455 C in 'a' .. 'z' or else
456 C in 'A' .. 'Z'
457 then
458 Set_Debug_Flag (C);
459 else
460 raise Bad_Switch;
461 end if;
462 end loop;
464 -- Make sure Zero_Cost_Exceptions is set if gnatdX set. This
465 -- is for backwards compatibility with old versions and usage.
467 if Debug_Flag_XX then
468 Zero_Cost_Exceptions_Set := True;
469 Zero_Cost_Exceptions_Val := True;
470 end if;
472 return;
474 -- Processing for f switch
476 when 'f' =>
477 Ptr := Ptr + 1;
478 Force_Compilations := True;
480 -- Processing for h switch
482 when 'h' =>
483 Ptr := Ptr + 1;
484 Usage_Requested := True;
486 -- Processing for i switch
488 when 'i' =>
489 Ptr := Ptr + 1;
490 In_Place_Mode := True;
492 -- Processing for j switch
494 when 'j' =>
495 Ptr := Ptr + 1;
497 declare
498 Max_Proc : Pos;
499 begin
500 Scan_Pos (Switch_Chars, Max, Ptr, Max_Proc);
501 Maximum_Processes := Positive (Max_Proc);
502 end;
504 -- Processing for k switch
506 when 'k' =>
507 Ptr := Ptr + 1;
508 Keep_Going := True;
510 -- Processing for l switch
512 when 'l' =>
513 Ptr := Ptr + 1;
514 Link_Only := True;
516 when 'M' =>
517 Ptr := Ptr + 1;
518 List_Dependencies := True;
520 -- Processing for n switch
522 when 'n' =>
523 Ptr := Ptr + 1;
524 Do_Not_Execute := True;
526 -- Processing for o switch
528 when 'o' =>
529 Ptr := Ptr + 1;
531 if Output_File_Name_Present then
532 raise Too_Many_Output_Files;
533 else
534 Output_File_Name_Present := True;
535 end if;
537 -- Processing for q switch
539 when 'q' =>
540 Ptr := Ptr + 1;
541 Quiet_Output := True;
543 -- Processing for s switch
545 when 's' =>
546 Ptr := Ptr + 1;
547 Check_Switches := True;
549 -- Processing for v switch
551 when 'v' =>
552 Ptr := Ptr + 1;
553 Verbose_Mode := True;
555 -- Processing for z switch
557 when 'z' =>
558 Ptr := Ptr + 1;
559 No_Main_Subprogram := True;
561 -- Ignore extra switch character
563 when '/' | '-' =>
564 Ptr := Ptr + 1;
566 -- Anything else is an error (illegal switch character)
568 when others =>
569 raise Bad_Switch;
571 end case;
572 end loop;
574 exception
575 when Bad_Switch =>
576 Osint.Fail ("invalid switch: ", (1 => C));
578 when Bad_Switch_Value =>
579 Osint.Fail ("numeric value too big for switch: ", (1 => C));
581 when Missing_Switch_Value =>
582 Osint.Fail ("missing numeric value for switch: ", (1 => C));
584 when Too_Many_Output_Files =>
585 Osint.Fail ("duplicate -o switch");
587 end Scan_Make_Switches;
589 end Switch.M;