* c-decl.c (duplicate_decls): Conditionalize DECL_SAVED_TREE copy.
[official-gcc.git] / gcc / ada / bindgen.adb
blob677e495cd7993d288f2221793bbfd2ceed8a6293
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- B I N D G E N --
6 -- --
7 -- B o d y --
8 -- --
9 -- $Revision: 1.201 $
10 -- --
11 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
12 -- --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
23 -- --
24 -- GNAT was originally developed by the GNAT team at New York University. --
25 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
26 -- --
27 ------------------------------------------------------------------------------
29 with ALI; use ALI;
30 with Binde; use Binde;
31 with Butil; use Butil;
32 with Casing; use Casing;
33 with Fname; use Fname;
34 with GNAT.OS_Lib; use GNAT.OS_Lib;
35 with Gnatvsn; use Gnatvsn;
36 with Hostparm;
37 with Namet; use Namet;
38 with Opt; use Opt;
39 with Osint; use Osint;
40 with Output; use Output;
41 with Types; use Types;
42 with Sdefault; use Sdefault;
43 with System; use System;
45 with GNAT.Heap_Sort_A; use GNAT.Heap_Sort_A;
47 package body Bindgen is
49 Statement_Buffer : String (1 .. 1000);
50 -- Buffer used for constructing output statements
52 Last : Natural := 0;
53 -- Last location in Statement_Buffer currently set
55 With_DECGNAT : Boolean := False;
56 -- Flag which indicates whether the program uses the DECGNAT library
57 -- (presence of the unit System.Aux_DEC.DECLIB)
59 With_GNARL : Boolean := False;
60 -- Flag which indicates whether the program uses the GNARL library
61 -- (presence of the unit System.OS_Interface)
63 Num_Elab_Calls : Nat := 0;
64 -- Number of generated calls to elaboration routines
66 subtype chars_ptr is Address;
68 -----------------------
69 -- Local Subprograms --
70 -----------------------
72 procedure WBI (Info : String) renames Osint.Write_Binder_Info;
73 -- Convenient shorthand used throughout
75 function ABE_Boolean_Required (U : Unit_Id) return Boolean;
76 -- Given a unit id value U, determines if the corresponding unit requires
77 -- an access-before-elaboration check variable, i.e. it is a non-predefined
78 -- body for which no pragma Elaborate, Elaborate_All or Elaborate_Body is
79 -- present, and thus could require ABE checks.
81 procedure Resolve_Binder_Options;
82 -- Set the value of With_GNARL and With_DECGNAT. The latter only on VMS
83 -- since it tests for a package named "dec" which might cause a conflict
84 -- on non-VMS systems.
86 procedure Gen_Adainit_Ada;
87 -- Generates the Adainit procedure (Ada code case)
89 procedure Gen_Adainit_C;
90 -- Generates the Adainit procedure (C code case)
92 procedure Gen_Adafinal_Ada;
93 -- Generate the Adafinal procedure (Ada code case)
95 procedure Gen_Adafinal_C;
96 -- Generate the Adafinal procedure (C code case)
98 procedure Gen_Elab_Calls_Ada;
99 -- Generate sequence of elaboration calls (Ada code case)
101 procedure Gen_Elab_Calls_C;
102 -- Generate sequence of elaboration calls (C code case)
104 procedure Gen_Elab_Order_Ada;
105 -- Generate comments showing elaboration order chosen (Ada case)
107 procedure Gen_Elab_Order_C;
108 -- Generate comments showing elaboration order chosen (C case)
110 procedure Gen_Elab_Defs_C;
111 -- Generate sequence of definitions for elaboration routines (C code case)
113 procedure Gen_Exception_Table_Ada;
114 -- Generate binder exception table (Ada code case). This consists of
115 -- declarations followed by a begin followed by a call. If zero cost
116 -- exceptions are not active, then only the begin is generated.
118 procedure Gen_Exception_Table_C;
119 -- Generate binder exception table (C code case). This has no effect
120 -- if zero cost exceptions are not active, otherwise it generates a
121 -- set of declarations followed by a call.
123 procedure Gen_Main_Ada;
124 -- Generate procedure main (Ada code case)
126 procedure Gen_Main_C;
127 -- Generate main() procedure (C code case)
129 procedure Gen_Object_Files_Options;
130 -- Output comments containing a list of the full names of the object
131 -- files to be linked and the list of linker options supplied by
132 -- Linker_Options pragmas in the source. (C and Ada code case)
134 procedure Gen_Output_File_Ada (Filename : String);
135 -- Generate output file (Ada code case)
137 procedure Gen_Output_File_C (Filename : String);
138 -- Generate output file (C code case)
140 procedure Gen_Scalar_Values;
141 -- Generates scalar initialization values for -Snn. A single procedure
142 -- handles both the Ada and C cases, since there is much common code.
144 procedure Gen_Versions_Ada;
145 -- Output series of definitions for unit versions (Ada code case)
147 procedure Gen_Versions_C;
148 -- Output series of definitions for unit versions (C code case)
150 function Get_Ada_Main_Name return String;
151 -- This function is used in the Ada main output case to compute a usable
152 -- name for the generated main program. The normal main program name is
153 -- Ada_Main, but this won't work if the user has a unit with this name.
154 -- This function tries Ada_Main first, and if there is such a clash, then
155 -- it tries Ada_Name_01, Ada_Name_02 ... Ada_Name_99 in sequence.
157 function Get_Main_Name return String;
158 -- This function is used in the Ada main output case to compute the
159 -- correct external main program. It is "main" by default, except on
160 -- VxWorks where it is the name of the Ada main name without the "_ada".
161 -- the -Mname binder option overrides the default with name.
163 function Lt_Linker_Option (Op1, Op2 : Natural) return Boolean;
164 -- Compare linker options, when sorting, first according to
165 -- Is_Internal_File (internal files come later) and then by elaboration
166 -- order position (latest to earliest) except its not possible to
167 -- distinguish between a linker option in the spec and one in the body.
169 procedure Move_Linker_Option (From : Natural; To : Natural);
170 -- Move routine for sorting linker options
172 procedure Public_Version_Warning;
173 -- Emit a warning concerning the use of the Public version under
174 -- certain circumstances. See details in body.
176 procedure Set_Char (C : Character);
177 -- Set given character in Statement_Buffer at the Last + 1 position
178 -- and increment Last by one to reflect the stored character.
180 procedure Set_Int (N : Int);
181 -- Set given value in decimal in Statement_Buffer with no spaces
182 -- starting at the Last + 1 position, and updating Last past the value.
183 -- A minus sign is output for a negative value.
185 procedure Set_Main_Program_Name;
186 -- Given the main program name in Name_Buffer (length in Name_Len)
187 -- generate the name of the routine to be used in the call. The name
188 -- is generated starting at Last + 1, and Last is updated past it.
190 procedure Set_Name_Buffer;
191 -- Set the value stored in positions 1 .. Name_Len of the Name_Buffer.
193 procedure Set_String (S : String);
194 -- Sets characters of given string in Statement_Buffer, starting at the
195 -- Last + 1 position, and updating last past the string value.
197 procedure Set_Unit_Name;
198 -- Given a unit name in the Name_Buffer, copies it to Statement_Buffer,
199 -- starting at the Last + 1 position, and updating last past the value.
200 -- changing periods to double underscores, and updating Last appropriately.
202 procedure Set_Unit_Number (U : Unit_Id);
203 -- Sets unit number (first unit is 1, leading zeroes output to line
204 -- up all output unit numbers nicely as required by the value, and
205 -- by the total number of units.
207 procedure Tab_To (N : Natural);
208 -- If Last is greater than or equal to N, no effect, otherwise store
209 -- blanks in Statement_Buffer bumping Last, until Last = N.
211 function Value (chars : chars_ptr) return String;
212 -- Return C NUL-terminated string at chars as an Ada string
214 procedure Write_Info_Ada_C (Ada : String; C : String; Common : String);
215 -- For C code case, write C & Common, for Ada case write Ada & Common
216 -- to current binder output file using Write_Binder_Info.
218 procedure Write_Statement_Buffer;
219 -- Write out contents of statement buffer up to Last, and reset Last to 0
221 procedure Write_Statement_Buffer (S : String);
222 -- First writes its argument (using Set_String (S)), then writes out the
223 -- contents of statement buffer up to Last, and reset Last to 0
225 --------------------------
226 -- ABE_Boolean_Required --
227 --------------------------
229 function ABE_Boolean_Required (U : Unit_Id) return Boolean is
230 Typ : constant Unit_Type := Units.Table (U).Utype;
231 Unit : Unit_Id;
233 begin
234 if Typ /= Is_Body then
235 return False;
237 else
238 Unit := U + 1;
240 return (not Units.Table (Unit).Pure)
241 and then
242 (not Units.Table (Unit).Preelab)
243 and then
244 (not Units.Table (Unit).Elaborate_Body)
245 and then
246 (not Units.Table (Unit).Predefined);
247 end if;
248 end ABE_Boolean_Required;
250 ----------------------
251 -- Gen_Adafinal_Ada --
252 ----------------------
254 procedure Gen_Adafinal_Ada is
255 begin
256 WBI ("");
257 WBI (" procedure " & Ada_Final_Name.all & " is");
258 WBI (" begin");
260 -- If compiling for the JVM, we directly call Adafinal because
261 -- we don't import it via Do_Finalize (see Gen_Output_File_Ada).
263 if Hostparm.Java_VM then
264 WBI (" System.Standard_Library.Adafinal;");
265 else
266 WBI (" Do_Finalize;");
267 end if;
269 WBI (" end " & Ada_Final_Name.all & ";");
270 end Gen_Adafinal_Ada;
272 --------------------
273 -- Gen_Adafinal_C --
274 --------------------
276 procedure Gen_Adafinal_C is
277 begin
278 WBI ("void " & Ada_Final_Name.all & " () {");
279 WBI (" system__standard_library__adafinal ();");
280 WBI ("}");
281 WBI ("");
282 end Gen_Adafinal_C;
284 ---------------------
285 -- Gen_Adainit_Ada --
286 ---------------------
288 procedure Gen_Adainit_Ada is
289 begin
290 WBI (" procedure " & Ada_Init_Name.all & " is");
292 -- Generate externals for elaboration entities
294 for E in Elab_Order.First .. Elab_Order.Last loop
295 declare
296 Unum : constant Unit_Id := Elab_Order.Table (E);
297 U : Unit_Record renames Units.Table (Unum);
299 begin
300 if U.Set_Elab_Entity then
301 Set_String (" ");
302 Set_String ("E");
303 Set_Unit_Number (Unum);
304 Set_String (" : Boolean; pragma Import (Ada, ");
305 Set_String ("E");
306 Set_Unit_Number (Unum);
307 Set_String (", """);
308 Get_Name_String (U.Uname);
310 -- In the case of JGNAT we need to emit an Import name
311 -- that includes the class name (using '$' separators
312 -- in the case of a child unit name).
314 if Hostparm.Java_VM then
315 for J in 1 .. Name_Len - 2 loop
316 if Name_Buffer (J) /= '.' then
317 Set_Char (Name_Buffer (J));
318 else
319 Set_String ("$");
320 end if;
321 end loop;
323 Set_String (".");
325 -- If the unit name is very long, then split the
326 -- Import link name across lines using "&" (occurs
327 -- in some C2 tests).
329 if 2 * Name_Len + 60 > Hostparm.Max_Line_Length then
330 Set_String (""" &");
331 Write_Statement_Buffer;
332 Set_String (" """);
333 end if;
334 end if;
336 Set_Unit_Name;
337 Set_String ("_E"");");
338 Write_Statement_Buffer;
339 end if;
340 end;
341 end loop;
343 Write_Statement_Buffer;
345 -- Normal case (no pragma No_Run_Time). The global values are
346 -- assigned using the runtime routine Set_Globals (we have to use
347 -- the routine call, rather than define the globals in the binder
348 -- file to deal with cross-library calls in some systems.
350 if not No_Run_Time_Specified then
351 WBI ("");
352 WBI (" procedure Set_Globals");
353 WBI (" (Main_Priority : Integer;");
354 WBI (" Time_Slice_Value : Integer;");
355 WBI (" WC_Encoding : Character;");
356 WBI (" Locking_Policy : Character;");
357 WBI (" Queuing_Policy : Character;");
358 WBI (" Task_Dispatching_Policy : Character;");
359 WBI (" Adafinal : System.Address;");
360 WBI (" Unreserve_All_Interrupts : Integer;");
361 WBI (" Exception_Tracebacks : Integer);");
362 WBI (" pragma Import (C, Set_Globals, ""__gnat_set_globals"");");
363 WBI ("");
365 -- Import entry point for elaboration time signal handler
366 -- installation, and indication of whether it's been called
367 -- previously
368 WBI ("");
369 WBI (" procedure Install_Handler;");
370 WBI (" pragma Import (C, Install_Handler, " &
371 """__gnat_install_handler"");");
372 WBI ("");
373 WBI (" Handler_Installed : Integer;");
374 WBI (" pragma Import (C, Handler_Installed, " &
375 """__gnat_handler_installed"");");
377 -- Generate exception table
379 Gen_Exception_Table_Ada;
381 -- Generate the call to Set_Globals
383 WBI (" Set_Globals");
385 Set_String (" (Main_Priority => ");
386 Set_Int (ALIs.Table (ALIs.First).Main_Priority);
387 Set_Char (',');
388 Write_Statement_Buffer;
390 Set_String (" Time_Slice_Value => ");
392 if Task_Dispatching_Policy_Specified = 'F'
393 and then ALIs.Table (ALIs.First).Time_Slice_Value = -1
394 then
395 Set_Int (0);
396 else
397 Set_Int (ALIs.Table (ALIs.First).Time_Slice_Value);
398 end if;
400 Set_Char (',');
401 Write_Statement_Buffer;
403 Set_String (" WC_Encoding => '");
404 Set_Char (ALIs.Table (ALIs.First).WC_Encoding);
405 Set_String ("',");
406 Write_Statement_Buffer;
408 Set_String (" Locking_Policy => '");
409 Set_Char (Locking_Policy_Specified);
410 Set_String ("',");
411 Write_Statement_Buffer;
413 Set_String (" Queuing_Policy => '");
414 Set_Char (Queuing_Policy_Specified);
415 Set_String ("',");
416 Write_Statement_Buffer;
418 Set_String (" Task_Dispatching_Policy => '");
419 Set_Char (Task_Dispatching_Policy_Specified);
420 Set_String ("',");
421 Write_Statement_Buffer;
423 WBI (" Adafinal => System.Null_Address,");
425 Set_String (" Unreserve_All_Interrupts => ");
427 if Unreserve_All_Interrupts_Specified then
428 Set_String ("1");
429 else
430 Set_String ("0");
431 end if;
433 Set_String (",");
434 Write_Statement_Buffer;
436 Set_String (" Exception_Tracebacks => ");
438 if Exception_Tracebacks then
439 Set_String ("1");
440 else
441 Set_String ("0");
442 end if;
444 Set_String (");");
445 Write_Statement_Buffer;
447 -- Generate call to Install_Handler
448 WBI ("");
449 WBI (" if Handler_Installed = 0 then");
450 WBI (" Install_Handler;");
451 WBI (" end if;");
453 -- Case of pragma No_Run_Time present. Globals are not needed since
454 -- there are no runtime routines to make use of them, and no routine
455 -- to store them in any case! Also no exception tables are needed.
457 else
458 WBI (" begin");
459 WBI (" null;");
460 end if;
462 Gen_Elab_Calls_Ada;
464 WBI (" end " & Ada_Init_Name.all & ";");
465 end Gen_Adainit_Ada;
467 -------------------
468 -- Gen_Adainit_C --
469 --------------------
471 procedure Gen_Adainit_C is
472 begin
473 WBI ("void " & Ada_Init_Name.all & " ()");
474 WBI ("{");
476 -- Generate externals for elaboration entities
478 for E in Elab_Order.First .. Elab_Order.Last loop
479 declare
480 Unum : constant Unit_Id := Elab_Order.Table (E);
481 U : Unit_Record renames Units.Table (Unum);
483 begin
484 if U.Set_Elab_Entity then
485 Set_String (" extern char ");
486 Get_Name_String (U.Uname);
487 Set_Unit_Name;
488 Set_String ("_E;");
489 Write_Statement_Buffer;
490 end if;
491 end;
492 end loop;
494 Write_Statement_Buffer;
496 -- Code for normal case (no pragma No_Run_Time in use)
498 if not No_Run_Time_Specified then
500 Gen_Exception_Table_C;
502 -- Generate call to set the runtime global variables defined in
503 -- a-init.c. We define the varables in a-init.c, rather than in
504 -- the binder generated file itself to avoid undefined externals
505 -- when the runtime is linked as a shareable image library.
507 -- We call the routine from inside adainit() because this works for
508 -- both programs with and without binder generated "main" functions.
510 WBI (" __gnat_set_globals (");
512 Set_String (" ");
513 Set_Int (ALIs.Table (ALIs.First).Main_Priority);
514 Set_Char (',');
515 Tab_To (15);
516 Set_String ("/* Main_Priority */");
517 Write_Statement_Buffer;
519 Set_String (" ");
521 if Task_Dispatching_Policy = 'F'
522 and then ALIs.Table (ALIs.First).Time_Slice_Value = -1
523 then
524 Set_Int (0);
525 else
526 Set_Int (ALIs.Table (ALIs.First).Time_Slice_Value);
527 end if;
529 Set_Char (',');
530 Tab_To (15);
531 Set_String ("/* Time_Slice_Value */");
532 Write_Statement_Buffer;
534 Set_String (" '");
535 Set_Char (ALIs.Table (ALIs.First).WC_Encoding);
536 Set_String ("',");
537 Tab_To (15);
538 Set_String ("/* WC_Encoding */");
539 Write_Statement_Buffer;
541 Set_String (" '");
542 Set_Char (Locking_Policy_Specified);
543 Set_String ("',");
544 Tab_To (15);
545 Set_String ("/* Locking_Policy */");
546 Write_Statement_Buffer;
548 Set_String (" '");
549 Set_Char (Queuing_Policy_Specified);
550 Set_String ("',");
551 Tab_To (15);
552 Set_String ("/* Queuing_Policy */");
553 Write_Statement_Buffer;
555 Set_String (" '");
556 Set_Char (Task_Dispatching_Policy_Specified);
557 Set_String ("',");
558 Tab_To (15);
559 Set_String ("/* Tasking_Dispatching_Policy */");
560 Write_Statement_Buffer;
562 Set_String (" ");
563 Set_String ("0,");
564 Tab_To (15);
565 Set_String ("/* Finalization routine address, not used anymore */");
566 Write_Statement_Buffer;
568 Set_String (" ");
569 Set_Int (Boolean'Pos (Unreserve_All_Interrupts_Specified));
570 Set_String (",");
571 Tab_To (15);
572 Set_String ("/* Unreserve_All_Interrupts */");
573 Write_Statement_Buffer;
575 Set_String (" ");
576 Set_Int (Boolean'Pos (Exception_Tracebacks));
577 Set_String (");");
578 Tab_To (15);
579 Set_String ("/* Exception_Tracebacks */");
580 Write_Statement_Buffer;
582 -- Install elaboration time signal handler
583 WBI (" if (__gnat_handler_installed == 0)");
584 WBI (" {");
585 WBI (" __gnat_install_handler ();");
586 WBI (" }");
588 -- Case where No_Run_Time pragma is present (no globals required)
589 -- Nothing more needs to be done in this case.
591 else
592 null;
593 end if;
595 WBI ("");
596 Gen_Elab_Calls_C;
597 WBI ("}");
598 end Gen_Adainit_C;
600 ------------------------
601 -- Gen_Elab_Calls_Ada --
602 ------------------------
604 procedure Gen_Elab_Calls_Ada is
605 begin
607 for E in Elab_Order.First .. Elab_Order.Last loop
608 declare
609 Unum : constant Unit_Id := Elab_Order.Table (E);
610 U : Unit_Record renames Units.Table (Unum);
612 Unum_Spec : Unit_Id;
613 -- This is the unit number of the spec that corresponds to
614 -- this entry. It is the same as Unum except when the body
615 -- and spec are different and we are currently processing
616 -- the body, in which case it is the spec (Unum + 1).
618 procedure Set_Elab_Entity;
619 -- Set name of elaboration entity flag
621 procedure Set_Elab_Entity is
622 begin
623 Get_Decoded_Name_String_With_Brackets (U.Uname);
624 Name_Len := Name_Len - 2;
625 Set_Casing (U.Icasing);
626 Set_Name_Buffer;
627 end Set_Elab_Entity;
629 begin
630 if U.Utype = Is_Body then
631 Unum_Spec := Unum + 1;
632 else
633 Unum_Spec := Unum;
634 end if;
636 -- Case of no elaboration code
638 if U.No_Elab then
640 -- The only case in which we have to do something is if
641 -- this is a body, with a separate spec, where the separate
642 -- spec has an elaboration entity defined.
644 -- In that case, this is where we set the elaboration entity
645 -- to True, we do not need to test if this has already been
646 -- done, since it is quicker to set the flag than to test it.
648 if U.Utype = Is_Body
649 and then Units.Table (Unum_Spec).Set_Elab_Entity
650 then
651 Set_String (" E");
652 Set_Unit_Number (Unum_Spec);
653 Set_String (" := True;");
654 Write_Statement_Buffer;
655 end if;
657 -- Here if elaboration code is present. We generate:
659 -- if not uname_E then
660 -- uname'elab_[spec|body];
661 -- uname_E := True;
662 -- end if;
664 -- The uname_E assignment is skipped if this is a separate spec,
665 -- since the assignment will be done when we process the body.
667 else
668 Set_String (" if not E");
669 Set_Unit_Number (Unum_Spec);
670 Set_String (" then");
671 Write_Statement_Buffer;
673 Set_String (" ");
674 Get_Decoded_Name_String_With_Brackets (U.Uname);
676 if Name_Buffer (Name_Len) = 's' then
677 Name_Buffer (Name_Len - 1 .. Name_Len + 8) := "'elab_spec";
678 else
679 Name_Buffer (Name_Len - 1 .. Name_Len + 8) := "'elab_body";
680 end if;
682 Name_Len := Name_Len + 8;
683 Set_Casing (U.Icasing);
684 Set_Name_Buffer;
685 Set_Char (';');
686 Write_Statement_Buffer;
688 if U.Utype /= Is_Spec then
689 Set_String (" E");
690 Set_Unit_Number (Unum_Spec);
691 Set_String (" := True;");
692 Write_Statement_Buffer;
693 end if;
695 WBI (" end if;");
696 end if;
697 end;
698 end loop;
700 end Gen_Elab_Calls_Ada;
702 ----------------------
703 -- Gen_Elab_Calls_C --
704 ----------------------
706 procedure Gen_Elab_Calls_C is
707 begin
709 for E in Elab_Order.First .. Elab_Order.Last loop
710 declare
711 Unum : constant Unit_Id := Elab_Order.Table (E);
712 U : Unit_Record renames Units.Table (Unum);
714 Unum_Spec : Unit_Id;
715 -- This is the unit number of the spec that corresponds to
716 -- this entry. It is the same as Unum except when the body
717 -- and spec are different and we are currently processing
718 -- the body, in which case it is the spec (Unum + 1).
720 begin
721 if U.Utype = Is_Body then
722 Unum_Spec := Unum + 1;
723 else
724 Unum_Spec := Unum;
725 end if;
727 -- Case of no elaboration code
729 if U.No_Elab then
731 -- The only case in which we have to do something is if
732 -- this is a body, with a separate spec, where the separate
733 -- spec has an elaboration entity defined.
735 -- In that case, this is where we set the elaboration entity
736 -- to True, we do not need to test if this has already been
737 -- done, since it is quicker to set the flag than to test it.
739 if U.Utype = Is_Body
740 and then Units.Table (Unum_Spec).Set_Elab_Entity
741 then
742 Set_String (" ");
743 Get_Name_String (U.Uname);
744 Set_Unit_Name;
745 Set_String ("_E = 1;");
746 Write_Statement_Buffer;
747 end if;
749 -- Here if elaboration code is present. We generate:
751 -- if (uname_E == 0) {
752 -- uname__elab[s|b] ();
753 -- uname_E++;
754 -- }
756 -- The uname_E assignment is skipped if this is a separate spec,
757 -- since the assignment will be done when we process the body.
759 else
760 Set_String (" if (");
761 Get_Name_String (U.Uname);
762 Set_Unit_Name;
763 Set_String ("_E == 0) {");
764 Write_Statement_Buffer;
766 Set_String (" ");
767 Set_Unit_Name;
768 Set_String ("___elab");
769 Set_Char (Name_Buffer (Name_Len)); -- 's' or 'b' for spec/body
770 Set_String (" ();");
771 Write_Statement_Buffer;
773 if U.Utype /= Is_Spec then
774 Set_String (" ");
775 Set_Unit_Name;
776 Set_String ("_E++;");
777 Write_Statement_Buffer;
778 end if;
780 WBI (" }");
781 end if;
782 end;
783 end loop;
785 end Gen_Elab_Calls_C;
787 ----------------------
788 -- Gen_Elab_Defs_C --
789 ----------------------
791 procedure Gen_Elab_Defs_C is
792 begin
793 for E in Elab_Order.First .. Elab_Order.Last loop
795 -- Generate declaration of elaboration procedure if elaboration
796 -- needed. Note that passive units are always excluded.
798 if not Units.Table (Elab_Order.Table (E)).No_Elab then
799 Get_Name_String (Units.Table (Elab_Order.Table (E)).Uname);
800 Set_String ("extern void ");
801 Set_Unit_Name;
802 Set_String ("___elab");
803 Set_Char (Name_Buffer (Name_Len)); -- 's' or 'b' for spec/body
804 Set_String (" PARAMS ((void));");
805 Write_Statement_Buffer;
806 end if;
808 end loop;
810 WBI ("");
811 end Gen_Elab_Defs_C;
813 ------------------------
814 -- Gen_Elab_Order_Ada --
815 ------------------------
817 procedure Gen_Elab_Order_Ada is
818 begin
819 WBI ("");
820 WBI (" -- BEGIN ELABORATION ORDER");
822 for J in Elab_Order.First .. Elab_Order.Last loop
823 Set_String (" -- ");
824 Get_Unit_Name_String (Units.Table (Elab_Order.Table (J)).Uname);
825 Set_Name_Buffer;
826 Write_Statement_Buffer;
827 end loop;
829 WBI (" -- END ELABORATION ORDER");
830 end Gen_Elab_Order_Ada;
832 ----------------------
833 -- Gen_Elab_Order_C --
834 ----------------------
836 procedure Gen_Elab_Order_C is
837 begin
838 WBI ("");
839 WBI ("/* BEGIN ELABORATION ORDER");
841 for J in Elab_Order.First .. Elab_Order.Last loop
842 Get_Unit_Name_String (Units.Table (Elab_Order.Table (J)).Uname);
843 Set_Name_Buffer;
844 Write_Statement_Buffer;
845 end loop;
847 WBI (" END ELABORATION ORDER */");
848 end Gen_Elab_Order_C;
850 -----------------------------
851 -- Gen_Exception_Table_Ada --
852 -----------------------------
854 procedure Gen_Exception_Table_Ada is
855 Num : Nat;
856 Last : ALI_Id := No_ALI_Id;
858 begin
859 if not Zero_Cost_Exceptions_Specified then
860 WBI (" begin");
861 return;
862 end if;
864 -- The code we generate looks like
866 -- procedure SDP_Table_Build
867 -- (SDP_Addresses : System.Address;
868 -- SDP_Count : Natural;
869 -- Elab_Addresses : System.Address;
870 -- Elab_Addr_Count : Natural);
871 -- pragma Import (C, SDP_Table_Build, "__gnat_SDP_Table_Build");
873 -- ST : aliased constant array (1 .. nnn) of System.Address := (
874 -- unit_name_1'UET_Address,
875 -- unit_name_2'UET_Address,
876 -- ...
877 -- unit_name_3'UET_Address,
879 -- EA : aliased constant array (1 .. eee) of System.Address := (
880 -- adainit'Code_Address,
881 -- adafinal'Code_Address,
882 -- unit_name'elab[spec|body]'Code_Address,
883 -- unit_name'elab[spec|body]'Code_Address,
884 -- unit_name'elab[spec|body]'Code_Address,
885 -- unit_name'elab[spec|body]'Code_Address);
887 -- begin
888 -- SDP_Table_Build (ST'Address, nnn, EA'Address, eee);
890 Num := 0;
891 for A in ALIs.First .. ALIs.Last loop
892 if ALIs.Table (A).Unit_Exception_Table then
893 Num := Num + 1;
894 Last := A;
895 end if;
896 end loop;
898 WBI (" procedure SDP_Table_Build");
899 WBI (" (SDP_Addresses : System.Address;");
900 WBI (" SDP_Count : Natural;");
901 WBI (" Elab_Addresses : System.Address;");
902 WBI (" Elab_Addr_Count : Natural);");
903 WBI (" " &
904 "pragma Import (C, SDP_Table_Build, ""__gnat_SDP_Table_Build"");");
906 WBI (" ");
907 Set_String (" ST : aliased constant array (1 .. ");
908 Set_Int (Num);
909 Set_String (") of System.Address := (");
911 if Num = 1 then
912 Set_String ("1 => A1);");
913 Write_Statement_Buffer;
915 else
916 Write_Statement_Buffer;
918 for A in ALIs.First .. ALIs.Last loop
919 if ALIs.Table (A).Unit_Exception_Table then
920 Get_Decoded_Name_String_With_Brackets
921 (Units.Table (ALIs.Table (A).First_Unit).Uname);
922 Set_Casing (Mixed_Case);
923 Set_String (" ");
924 Set_String (Name_Buffer (1 .. Name_Len - 2));
925 Set_String ("'UET_Address");
927 if A = Last then
928 Set_String (");");
929 else
930 Set_Char (',');
931 end if;
933 Write_Statement_Buffer;
934 end if;
935 end loop;
936 end if;
938 WBI (" ");
939 Set_String (" EA : aliased constant array (1 .. ");
940 Set_Int (Num_Elab_Calls + 2);
941 Set_String (") of System.Address := (");
942 Write_Statement_Buffer;
943 WBI (" " & Ada_Init_Name.all & "'Code_Address,");
945 -- If compiling for the JVM, we directly reference Adafinal because
946 -- we don't import it via Do_Finalize (see Gen_Output_File_Ada).
948 if Hostparm.Java_VM then
949 Set_String (" System.Standard_Library.Adafinal'Code_Address");
950 else
951 Set_String (" Do_Finalize'Code_Address");
952 end if;
954 for E in Elab_Order.First .. Elab_Order.Last loop
955 Get_Decoded_Name_String_With_Brackets
956 (Units.Table (Elab_Order.Table (E)).Uname);
958 if Units.Table (Elab_Order.Table (E)).No_Elab then
959 null;
961 else
962 Set_Char (',');
963 Write_Statement_Buffer;
964 Set_String (" ");
966 if Name_Buffer (Name_Len) = 's' then
967 Name_Buffer (Name_Len - 1 .. Name_Len + 21) :=
968 "'elab_spec'code_address";
969 else
970 Name_Buffer (Name_Len - 1 .. Name_Len + 21) :=
971 "'elab_body'code_address";
972 end if;
974 Name_Len := Name_Len + 21;
975 Set_Casing (Units.Table (Elab_Order.Table (E)).Icasing);
976 Set_Name_Buffer;
977 end if;
978 end loop;
980 Set_String (");");
981 Write_Statement_Buffer;
983 WBI (" ");
984 WBI (" begin");
986 Set_String (" SDP_Table_Build (ST'Address, ");
987 Set_Int (Num);
988 Set_String (", EA'Address, ");
989 Set_Int (Num_Elab_Calls + 2);
990 Set_String (");");
991 Write_Statement_Buffer;
992 end Gen_Exception_Table_Ada;
994 ---------------------------
995 -- Gen_Exception_Table_C --
996 ---------------------------
998 procedure Gen_Exception_Table_C is
999 Num : Nat;
1000 Num2 : Nat;
1002 begin
1003 if not Zero_Cost_Exceptions_Specified then
1004 return;
1005 end if;
1007 -- The code we generate looks like
1009 -- extern void *__gnat_unitname1__SDP;
1010 -- extern void *__gnat_unitname2__SDP;
1011 -- ...
1013 -- void **st[nnn] = {
1014 -- &__gnat_unitname1__SDP,
1015 -- &__gnat_unitname2__SDP,
1016 -- ...
1017 -- &__gnat_unitnamen__SDP};
1019 -- extern void unitname1__elabb ();
1020 -- extern void unitname2__elabb ();
1021 -- ...
1023 -- void (*ea[eee]) () = {
1024 -- adainit,
1025 -- adafinal,
1026 -- unitname1___elab[b,s],
1027 -- unitname2___elab[b,s],
1028 -- ...
1029 -- unitnamen___elab[b,s]};
1031 -- __gnat_SDP_Table_Build (&st, nnn, &ea, eee);
1033 Num := 0;
1034 for A in ALIs.First .. ALIs.Last loop
1035 if ALIs.Table (A).Unit_Exception_Table then
1036 Num := Num + 1;
1038 Set_String (" extern void *__gnat_");
1039 Get_Name_String (Units.Table (ALIs.Table (A).First_Unit).Uname);
1040 Set_Unit_Name;
1041 Set_String ("__SDP");
1042 Set_Char (';');
1043 Write_Statement_Buffer;
1044 end if;
1045 end loop;
1047 WBI (" ");
1049 Set_String (" void **st[");
1050 Set_Int (Num);
1051 Set_String ("] = {");
1052 Write_Statement_Buffer;
1054 Num2 := 0;
1055 for A in ALIs.First .. ALIs.Last loop
1056 if ALIs.Table (A).Unit_Exception_Table then
1057 Num2 := Num2 + 1;
1059 Set_String (" &__gnat_");
1060 Get_Name_String (Units.Table (ALIs.Table (A).First_Unit).Uname);
1061 Set_Unit_Name;
1062 Set_String ("__SDP");
1064 if Num = Num2 then
1065 Set_String ("};");
1066 else
1067 Set_Char (',');
1068 end if;
1070 Write_Statement_Buffer;
1071 end if;
1072 end loop;
1074 WBI ("");
1075 for E in Elab_Order.First .. Elab_Order.Last loop
1076 Get_Name_String (Units.Table (Elab_Order.Table (E)).Uname);
1078 if Units.Table (Elab_Order.Table (E)).No_Elab then
1079 null;
1081 else
1082 Set_String (" extern void ");
1083 Set_Unit_Name;
1084 Set_String ("___elab");
1085 Set_Char (Name_Buffer (Name_Len)); -- 's' or 'b' for spec/body
1086 Set_String (" ();");
1087 Write_Statement_Buffer;
1088 end if;
1089 end loop;
1091 WBI ("");
1092 Set_String (" void (*ea[");
1093 Set_Int (Num_Elab_Calls + 2);
1094 Set_String ("]) () = {");
1095 Write_Statement_Buffer;
1097 WBI (" " & Ada_Init_Name.all & ",");
1098 Set_String (" system__standard_library__adafinal");
1100 for E in Elab_Order.First .. Elab_Order.Last loop
1101 Get_Name_String (Units.Table (Elab_Order.Table (E)).Uname);
1103 if Units.Table (Elab_Order.Table (E)).No_Elab then
1104 null;
1106 else
1107 Set_Char (',');
1108 Write_Statement_Buffer;
1109 Set_String (" ");
1110 Set_Unit_Name;
1111 Set_String ("___elab");
1112 Set_Char (Name_Buffer (Name_Len)); -- 's' or 'b' for spec/body
1113 end if;
1114 end loop;
1116 Set_String ("};");
1117 Write_Statement_Buffer;
1119 WBI (" ");
1121 Set_String (" __gnat_SDP_Table_Build (&st, ");
1122 Set_Int (Num);
1123 Set_String (", ea, ");
1124 Set_Int (Num_Elab_Calls + 2);
1125 Set_String (");");
1126 Write_Statement_Buffer;
1127 end Gen_Exception_Table_C;
1129 ------------------
1130 -- Gen_Main_Ada --
1131 ------------------
1133 procedure Gen_Main_Ada is
1134 Target : constant String_Ptr := Target_Name;
1135 VxWorks_Target : constant Boolean :=
1136 Target (Target'Last - 7 .. Target'Last) = "vxworks/";
1138 begin
1139 WBI ("");
1140 Set_String (" function ");
1141 Set_String (Get_Main_Name);
1143 if VxWorks_Target then
1144 Set_String (" return Integer is");
1145 Write_Statement_Buffer;
1147 else
1148 Write_Statement_Buffer;
1149 WBI (" (argc : Integer;");
1150 WBI (" argv : System.Address;");
1151 WBI (" envp : System.Address)");
1152 WBI (" return Integer");
1153 WBI (" is");
1154 end if;
1156 -- Initialize and Finalize are not used in No_Run_Time mode
1158 if not No_Run_Time_Specified then
1159 WBI (" procedure initialize;");
1160 WBI (" pragma Import (C, initialize, ""__gnat_initialize"");");
1161 WBI ("");
1162 WBI (" procedure finalize;");
1163 WBI (" pragma Import (C, finalize, ""__gnat_finalize"");");
1164 WBI ("");
1165 end if;
1167 -- Deal with declarations for main program case
1169 if not No_Main_Subprogram then
1171 -- To call the main program, we declare it using a pragma Import
1172 -- Ada with the right link name.
1174 -- It might seem more obvious to "with" the main program, and call
1175 -- it in the normal Ada manner. We do not do this for three reasons:
1177 -- 1. It is more efficient not to recompile the main program
1178 -- 2. We are not entitled to assume the source is accessible
1179 -- 3. We don't know what options to use to compile it
1181 -- It is really reason 3 that is most critical (indeed we used
1182 -- to generate the "with", but several regression tests failed).
1184 WBI ("");
1186 if ALIs.Table (ALIs.First).Main_Program = Func then
1187 WBI (" Result : Integer;");
1188 WBI ("");
1189 WBI (" function Ada_Main_Program return Integer;");
1191 else
1192 WBI (" procedure Ada_Main_Program;");
1193 end if;
1195 Set_String (" pragma Import (Ada, Ada_Main_Program, """);
1196 Get_Name_String (Units.Table (First_Unit_Entry).Uname);
1197 Set_Main_Program_Name;
1198 Set_String (""");");
1200 Write_Statement_Buffer;
1201 WBI ("");
1202 end if;
1204 WBI (" begin");
1206 -- On VxWorks, there are no command line arguments
1208 if VxWorks_Target then
1209 WBI (" gnat_argc := 0;");
1210 WBI (" gnat_argv := System.Null_Address;");
1211 WBI (" gnat_envp := System.Null_Address;");
1213 -- Normal case of command line arguments present
1215 else
1216 WBI (" gnat_argc := argc;");
1217 WBI (" gnat_argv := argv;");
1218 WBI (" gnat_envp := envp;");
1219 WBI ("");
1220 end if;
1222 if not No_Run_Time_Specified then
1223 WBI (" Initialize;");
1224 end if;
1226 WBI (" " & Ada_Init_Name.all & ";");
1228 if not No_Main_Subprogram then
1229 WBI (" Break_Start;");
1231 if ALIs.Table (ALIs.First).Main_Program = Proc then
1232 WBI (" Ada_Main_Program;");
1233 else
1234 WBI (" Result := Ada_Main_Program;");
1235 end if;
1236 end if;
1238 -- Adafinal is only called if we have a run time
1240 if not No_Run_Time_Specified then
1242 -- If compiling for the JVM, we directly call Adafinal because
1243 -- we don't import it via Do_Finalize (see Gen_Output_File_Ada).
1245 if Hostparm.Java_VM then
1246 WBI (" System.Standard_Library.Adafinal;");
1247 else
1248 WBI (" Do_Finalize;");
1249 end if;
1250 end if;
1252 -- Finalize is only called if we have a run time
1254 if not No_Run_Time_Specified then
1255 WBI (" Finalize;");
1256 end if;
1258 -- Return result
1260 if No_Main_Subprogram
1261 or else ALIs.Table (ALIs.First).Main_Program = Proc
1262 then
1263 WBI (" return (gnat_exit_status);");
1264 else
1265 WBI (" return (Result);");
1266 end if;
1268 WBI (" end;");
1269 end Gen_Main_Ada;
1271 ----------------
1272 -- Gen_Main_C --
1273 ----------------
1275 procedure Gen_Main_C is
1276 Target : constant String_Ptr := Target_Name;
1277 VxWorks_Target : constant Boolean :=
1278 Target (Target'Last - 7 .. Target'Last) = "vxworks/";
1280 begin
1281 Set_String ("int ");
1282 Set_String (Get_Main_Name);
1284 -- On VxWorks, there are no command line arguments
1286 if VxWorks_Target then
1287 Set_String (" ()");
1289 -- Normal case with command line arguments present
1291 else
1292 Set_String (" (argc, argv, envp)");
1293 end if;
1295 Write_Statement_Buffer;
1297 -- VxWorks doesn't have the notion of argc/argv
1299 if VxWorks_Target then
1300 WBI ("{");
1301 WBI (" int result;");
1302 WBI (" gnat_argc = 0;");
1303 WBI (" gnat_argv = 0;");
1304 WBI (" gnat_envp = 0;");
1306 -- Normal case of arguments present
1308 else
1309 WBI (" int argc;");
1310 WBI (" char **argv;");
1311 WBI (" char **envp;");
1312 WBI ("{");
1314 if ALIs.Table (ALIs.First).Main_Program = Func then
1315 WBI (" int result;");
1316 end if;
1318 WBI (" gnat_argc = argc;");
1319 WBI (" gnat_argv = argv;");
1320 WBI (" gnat_envp = envp;");
1321 WBI (" ");
1322 end if;
1324 -- The __gnat_initialize routine is used only if we have a run-time
1326 if not No_Run_Time_Specified then
1328 (" __gnat_initialize ();");
1329 end if;
1331 WBI (" " & Ada_Init_Name.all & " ();");
1333 if not No_Main_Subprogram then
1335 WBI (" __gnat_break_start ();");
1336 WBI (" ");
1338 -- Output main program name
1340 Get_Name_String (Units.Table (First_Unit_Entry).Uname);
1342 -- Main program is procedure case
1344 if ALIs.Table (ALIs.First).Main_Program = Proc then
1345 Set_String (" ");
1346 Set_Main_Program_Name;
1347 Set_String (" ();");
1348 Write_Statement_Buffer;
1350 -- Main program is function case
1352 else -- ALIs.Table (ALIs_First).Main_Program = Func
1353 Set_String (" result = ");
1354 Set_Main_Program_Name;
1355 Set_String (" ();");
1356 Write_Statement_Buffer;
1357 end if;
1359 end if;
1361 -- Adafinal is called only when we have a run-time
1363 if not No_Run_Time_Specified then
1364 WBI (" ");
1365 WBI (" system__standard_library__adafinal ();");
1366 end if;
1368 -- The finalize routine is used only if we have a run-time
1370 if not No_Run_Time_Specified then
1371 WBI (" __gnat_finalize ();");
1372 end if;
1374 if ALIs.Table (ALIs.First).Main_Program = Func then
1376 if Hostparm.OpenVMS then
1378 -- VMS must use the Posix exit routine in order to get an
1379 -- Unix compatible exit status.
1381 WBI (" __posix_exit (result);");
1383 else
1384 WBI (" exit (result);");
1385 end if;
1387 else
1389 if Hostparm.OpenVMS then
1390 -- VMS must use the Posix exit routine in order to get an
1391 -- Unix compatible exit status.
1392 WBI (" __posix_exit (gnat_exit_status);");
1393 else
1394 WBI (" exit (gnat_exit_status);");
1395 end if;
1396 end if;
1398 WBI ("}");
1399 end Gen_Main_C;
1401 ------------------------------
1402 -- Gen_Object_Files_Options --
1403 ------------------------------
1405 procedure Gen_Object_Files_Options is
1406 Lgnat : Integer;
1408 procedure Write_Linker_Option;
1409 -- Write binder info linker option.
1411 -------------------------
1412 -- Write_Linker_Option --
1413 -------------------------
1415 procedure Write_Linker_Option is
1416 Start : Natural;
1417 Stop : Natural;
1419 begin
1420 -- Loop through string, breaking at null's
1422 Start := 1;
1423 while Start < Name_Len loop
1425 -- Find null ending this section
1427 Stop := Start + 1;
1428 while Name_Buffer (Stop) /= ASCII.NUL
1429 and then Stop <= Name_Len loop
1430 Stop := Stop + 1;
1431 end loop;
1433 -- Process section if non-null
1435 if Stop > Start then
1436 if Output_Linker_Option_List then
1437 Write_Str (Name_Buffer (Start .. Stop - 1));
1438 Write_Eol;
1439 end if;
1440 Write_Info_Ada_C
1441 (" -- ", "", Name_Buffer (Start .. Stop - 1));
1442 end if;
1444 Start := Stop + 1;
1445 end loop;
1446 end Write_Linker_Option;
1448 -- Start of processing for Gen_Object_Files_Options
1450 begin
1451 WBI ("");
1452 Write_Info_Ada_C ("--", "/*", " BEGIN Object file/option list");
1454 for E in Elab_Order.First .. Elab_Order.Last loop
1456 -- If not spec that has an associated body, then generate a
1457 -- comment giving the name of the corresponding object file.
1459 if Units.Table (Elab_Order.Table (E)).Utype /= Is_Spec then
1460 Get_Name_String
1461 (ALIs.Table
1462 (Units.Table (Elab_Order.Table (E)).My_ALI).Ofile_Full_Name);
1464 -- If the presence of an object file is necessary or if it
1465 -- exists, then use it.
1467 if not Hostparm.Exclude_Missing_Objects
1468 or else
1469 GNAT.OS_Lib.Is_Regular_File (Name_Buffer (1 .. Name_Len))
1470 then
1471 Write_Info_Ada_C (" -- ", "", Name_Buffer (1 .. Name_Len));
1472 if Output_Object_List then
1473 Write_Str (Name_Buffer (1 .. Name_Len));
1474 Write_Eol;
1475 end if;
1477 -- Don't link with the shared library on VMS if an internal
1478 -- filename object is seen. Multiply defined symbols will
1479 -- result.
1481 if Hostparm.OpenVMS
1482 and then Is_Internal_File_Name
1483 (ALIs.Table
1484 (Units.Table (Elab_Order.Table (E)).My_ALI).Sfile)
1485 then
1486 Opt.Shared_Libgnat := False;
1487 end if;
1489 end if;
1490 end if;
1491 end loop;
1493 -- Add a "-Ldir" for each directory in the object path. We skip this
1494 -- in No_Run_Time mode, where we want more precise control of exactly
1495 -- what goes into the resulting object file
1497 if not No_Run_Time_Specified then
1498 for J in 1 .. Nb_Dir_In_Obj_Search_Path loop
1499 declare
1500 Dir : String_Ptr := Dir_In_Obj_Search_Path (J);
1502 begin
1503 Name_Len := 0;
1504 Add_Str_To_Name_Buffer ("-L");
1505 Add_Str_To_Name_Buffer (Dir.all);
1506 Write_Linker_Option;
1507 end;
1508 end loop;
1509 end if;
1511 -- Sort linker options
1513 Sort (Linker_Options.Last, Move_Linker_Option'Access,
1514 Lt_Linker_Option'Access);
1516 -- Write user linker options
1518 Lgnat := Linker_Options.Last + 1;
1520 for J in 1 .. Linker_Options.Last loop
1521 if not Linker_Options.Table (J).Internal_File then
1522 Get_Name_String (Linker_Options.Table (J).Name);
1523 Write_Linker_Option;
1524 else
1525 Lgnat := J;
1526 exit;
1527 end if;
1528 end loop;
1530 if not (No_Run_Time_Specified or else Opt.No_Stdlib) then
1532 Name_Len := 0;
1534 if Opt.Shared_Libgnat then
1535 Add_Str_To_Name_Buffer ("-shared");
1536 else
1537 Add_Str_To_Name_Buffer ("-static");
1538 end if;
1540 -- Write directly to avoid -K output.
1542 Write_Info_Ada_C (" -- ", "", Name_Buffer (1 .. Name_Len));
1544 if With_DECGNAT then
1545 Name_Len := 0;
1546 Add_Str_To_Name_Buffer ("-ldecgnat");
1547 Write_Linker_Option;
1548 end if;
1550 if With_GNARL then
1551 Name_Len := 0;
1552 Add_Str_To_Name_Buffer ("-lgnarl");
1553 Write_Linker_Option;
1554 end if;
1556 Name_Len := 0;
1557 Add_Str_To_Name_Buffer ("-lgnat");
1558 Write_Linker_Option;
1560 end if;
1562 -- Write internal linker options
1564 for J in Lgnat .. Linker_Options.Last loop
1565 Get_Name_String (Linker_Options.Table (J).Name);
1566 Write_Linker_Option;
1567 end loop;
1569 if Ada_Bind_File then
1570 WBI ("-- END Object file/option list ");
1571 else
1572 WBI (" END Object file/option list */");
1573 end if;
1575 end Gen_Object_Files_Options;
1577 ---------------------
1578 -- Gen_Output_File --
1579 ---------------------
1581 procedure Gen_Output_File (Filename : String) is
1583 function Public_Version return Boolean;
1584 -- Return true if the version number contains a 'p'
1586 function Public_Version return Boolean is
1587 begin
1588 for J in Gnat_Version_String'Range loop
1589 if Gnat_Version_String (J) = 'p' then
1590 return True;
1591 end if;
1592 end loop;
1594 return False;
1595 end Public_Version;
1597 -- Start of processing for Gen_Output_File
1599 begin
1600 -- Override Ada_Bind_File and Bind_Main_Program for Java since
1601 -- JGNAT only supports Ada code, and the main program is already
1602 -- generated by the compiler.
1604 if Hostparm.Java_VM then
1605 Ada_Bind_File := True;
1606 Bind_Main_Program := False;
1607 end if;
1609 -- Override time slice value if -T switch is set
1611 if Time_Slice_Set then
1612 ALIs.Table (ALIs.First).Time_Slice_Value := Opt.Time_Slice_Value;
1613 end if;
1615 -- Count number of elaboration calls
1617 for E in Elab_Order.First .. Elab_Order.Last loop
1618 if Units.Table (Elab_Order.Table (E)).No_Elab then
1619 null;
1620 else
1621 Num_Elab_Calls := Num_Elab_Calls + 1;
1622 end if;
1623 end loop;
1625 -- Get the time stamp of the former bind for public version warning
1627 if Public_Version then
1628 Record_Time_From_Last_Bind;
1629 end if;
1631 -- Generate output file in appropriate language
1633 if Ada_Bind_File then
1634 Gen_Output_File_Ada (Filename);
1635 else
1636 Gen_Output_File_C (Filename);
1637 end if;
1639 -- Periodically issue a warning when the public version is used on
1640 -- big projects
1642 if Public_Version then
1643 Public_Version_Warning;
1644 end if;
1645 end Gen_Output_File;
1647 -------------------------
1648 -- Gen_Output_File_Ada --
1649 -------------------------
1651 procedure Gen_Output_File_Ada (Filename : String) is
1653 Bfiles : Name_Id;
1654 -- Name of generated bind file (spec)
1656 Bfileb : Name_Id;
1657 -- Name of generated bind file (body)
1659 Ada_Main : constant String := Get_Ada_Main_Name;
1660 -- Name to be used for generated Ada main program. See the body of
1661 -- function Get_Ada_Main_Name for details on the form of the name.
1663 Target : constant String_Ptr := Target_Name;
1664 VxWorks_Target : constant Boolean :=
1665 Target (Target'Last - 7 .. Target'Last) = "vxworks/";
1667 begin
1668 -- Create spec first
1670 Create_Binder_Output (Filename, 's', Bfiles);
1672 if No_Run_Time_Specified then
1673 WBI ("pragma No_Run_Time;");
1674 end if;
1676 -- Generate with of System so we can reference System.Address, note
1677 -- that such a reference is safe even in No_Run_Time mode, since we
1678 -- do not need any run-time code for such a reference, and we output
1679 -- a pragma No_Run_Time for this compilation above.
1681 WBI ("with System;");
1683 -- Generate with of System.Initialize_Scalars if active
1685 if Initialize_Scalars_Used then
1686 WBI ("with System.Scalar_Values;");
1687 end if;
1689 Resolve_Binder_Options;
1691 if not No_Run_Time_Specified then
1693 -- Usually, adafinal is called using a pragma Import C. Since
1694 -- Import C doesn't have the same semantics for JGNAT, we use
1695 -- standard Ada.
1697 if Hostparm.Java_VM then
1698 WBI ("with System.Standard_Library;");
1699 end if;
1700 end if;
1702 WBI ("package " & Ada_Main & " is");
1704 -- Main program case
1706 if Bind_Main_Program then
1708 -- Generate argc/argv stuff
1710 WBI ("");
1711 WBI (" gnat_argc : Integer;");
1712 WBI (" gnat_argv : System.Address;");
1713 WBI (" gnat_envp : System.Address;");
1715 -- If we have a run time present, these variables are in the
1716 -- runtime data area for easy access from the runtime
1718 if not No_Run_Time_Specified then
1719 WBI ("");
1720 WBI (" pragma Import (C, gnat_argc);");
1721 WBI (" pragma Import (C, gnat_argv);");
1722 WBI (" pragma Import (C, gnat_envp);");
1723 end if;
1725 -- Define exit status. Again in normal mode, this is in the
1726 -- run-time library, and is initialized there, but in the no
1727 -- run time case, the variable is here and initialized here.
1729 WBI ("");
1731 if No_Run_Time_Specified then
1732 WBI (" gnat_exit_status : Integer := 0;");
1733 else
1734 WBI (" gnat_exit_status : Integer;");
1735 WBI (" pragma Import (C, gnat_exit_status);");
1736 end if;
1737 end if;
1739 -- Generate the GNAT_Version info only for the main program. Otherwise,
1740 -- it can lead under some circumstances to a symbol duplication during
1741 -- the link (for instance when a C program uses 2 Ada libraries)
1743 if Bind_Main_Program then
1744 WBI ("");
1745 WBI (" GNAT_Version : constant String :=");
1746 WBI (" ""GNAT Version: " &
1747 Gnat_Version_String & """;");
1748 WBI (" pragma Export (C, GNAT_Version, ""__gnat_version"");");
1749 end if;
1751 -- No need to generate a finalization routine if there is no
1752 -- runtime, since there is nothing to do in this case.
1754 if not No_Run_Time_Specified then
1755 WBI ("");
1756 WBI (" procedure " & Ada_Final_Name.all & ";");
1757 WBI (" pragma Export (C, " & Ada_Final_Name.all & ", """ &
1758 Ada_Final_Name.all & """);");
1759 end if;
1761 WBI ("");
1762 WBI (" procedure " & Ada_Init_Name.all & ";");
1763 WBI (" pragma Export (C, " & Ada_Init_Name.all & ", """ &
1764 Ada_Init_Name.all & """);");
1766 if Bind_Main_Program then
1768 -- If we have a run time, then Break_Start is defined there, but
1769 -- if there is no run-time, Break_Start is defined in this file.
1771 WBI ("");
1772 WBI (" procedure Break_Start;");
1774 if No_Run_Time_Specified then
1775 WBI (" pragma Export (C, Break_Start, ""__gnat_break_start"");");
1776 else
1777 WBI (" pragma Import (C, Break_Start, ""__gnat_break_start"");");
1778 end if;
1780 WBI ("");
1781 WBI (" function " & Get_Main_Name);
1783 -- Generate argument list (except on VxWorks, where none is present)
1785 if not VxWorks_Target then
1786 WBI (" (argc : Integer;");
1787 WBI (" argv : System.Address;");
1788 WBI (" envp : System.Address)");
1789 end if;
1791 WBI (" return Integer;");
1792 WBI (" pragma Export (C, " & Get_Main_Name & ", """ &
1793 Get_Main_Name & """);");
1794 end if;
1796 if Initialize_Scalars_Used then
1797 Gen_Scalar_Values;
1798 end if;
1800 Gen_Versions_Ada;
1801 Gen_Elab_Order_Ada;
1803 -- Spec is complete
1805 WBI ("");
1806 WBI ("end " & Ada_Main & ";");
1807 Close_Binder_Output;
1809 -- Prepare to write body
1811 Create_Binder_Output (Filename, 'b', Bfileb);
1813 -- Output Source_File_Name pragmas which look like
1815 -- pragma Source_File_Name (Ada_Main, Spec_File_Name => "sss");
1816 -- pragma Source_File_Name (Ada_Main, Body_File_Name => "bbb");
1818 -- where sss/bbb are the spec/body file names respectively
1820 Get_Name_String (Bfiles);
1821 Name_Buffer (Name_Len + 1 .. Name_Len + 3) := """);";
1823 WBI ("pragma Source_File_Name (" &
1824 Ada_Main &
1825 ", Spec_File_Name => """ &
1826 Name_Buffer (1 .. Name_Len + 3));
1828 Get_Name_String (Bfileb);
1829 Name_Buffer (Name_Len + 1 .. Name_Len + 3) := """);";
1831 WBI ("pragma Source_File_Name (" &
1832 Ada_Main &
1833 ", Body_File_Name => """ &
1834 Name_Buffer (1 .. Name_Len + 3));
1836 WBI ("");
1837 WBI ("package body " & Ada_Main & " is");
1839 -- Import the finalization procedure only if there is a runtime.
1841 if not No_Run_Time_Specified then
1843 -- In the Java case, pragma Import C cannot be used, so the
1844 -- standard Ada constructs will be used instead.
1846 if not Hostparm.Java_VM then
1847 WBI ("");
1848 WBI (" procedure Do_Finalize;");
1850 (" pragma Import (C, Do_Finalize, " &
1851 """system__standard_library__adafinal"");");
1852 WBI ("");
1853 end if;
1854 end if;
1856 Gen_Adainit_Ada;
1858 -- No need to generate a finalization routine if there is no
1859 -- runtime, since there is nothing to do in this case.
1861 if not No_Run_Time_Specified then
1862 Gen_Adafinal_Ada;
1863 end if;
1865 if Bind_Main_Program then
1867 -- In No_Run_Time mode, generate dummy body for Break_Start
1869 if No_Run_Time_Specified then
1870 WBI ("");
1871 WBI (" procedure Break_Start is");
1872 WBI (" begin");
1873 WBI (" null;");
1874 WBI (" end;");
1875 end if;
1877 Gen_Main_Ada;
1878 end if;
1880 -- Output object file list and the Ada body is complete
1882 Gen_Object_Files_Options;
1884 WBI ("");
1885 WBI ("end " & Ada_Main & ";");
1887 Close_Binder_Output;
1888 end Gen_Output_File_Ada;
1890 -----------------------
1891 -- Gen_Output_File_C --
1892 -----------------------
1894 procedure Gen_Output_File_C (Filename : String) is
1896 Bfile : Name_Id;
1897 -- Name of generated bind file
1899 begin
1900 Create_Binder_Output (Filename, 'c', Bfile);
1902 Resolve_Binder_Options;
1904 WBI ("#ifdef __STDC__");
1905 WBI ("#define PARAMS(paramlist) paramlist");
1906 WBI ("#else");
1907 WBI ("#define PARAMS(paramlist) ()");
1908 WBI ("#endif");
1909 WBI ("");
1911 WBI ("extern void __gnat_set_globals ");
1912 WBI (" PARAMS ((int, int, int, int, int, int, ");
1913 WBI (" void (*) PARAMS ((void)), int, int));");
1914 WBI ("extern void " & Ada_Final_Name.all & " PARAMS ((void));");
1915 WBI ("extern void " & Ada_Init_Name.all & " PARAMS ((void));");
1917 WBI ("extern void system__standard_library__adafinal PARAMS ((void));");
1919 if not No_Main_Subprogram then
1920 WBI ("extern int main PARAMS ((int, char **, char **));");
1921 if Hostparm.OpenVMS then
1922 WBI ("extern void __posix_exit PARAMS ((int));");
1923 else
1924 WBI ("extern void exit PARAMS ((int));");
1925 end if;
1927 WBI ("extern void __gnat_break_start PARAMS ((void));");
1928 Set_String ("extern ");
1930 if ALIs.Table (ALIs.First).Main_Program = Proc then
1931 Set_String ("void ");
1932 else
1933 Set_String ("int ");
1934 end if;
1936 Get_Name_String (Units.Table (First_Unit_Entry).Uname);
1937 Set_Main_Program_Name;
1938 Set_String (" PARAMS ((void));");
1939 Write_Statement_Buffer;
1940 end if;
1942 if not No_Run_Time_Specified then
1943 WBI ("extern void __gnat_initialize PARAMS ((void));");
1944 WBI ("extern void __gnat_finalize PARAMS ((void));");
1945 WBI ("extern void __gnat_install_handler PARAMS ((void));");
1946 end if;
1948 WBI ("");
1950 Gen_Elab_Defs_C;
1952 -- Imported variable used to track elaboration/finalization phase.
1953 -- Used only when we have a runtime.
1955 if not No_Run_Time_Specified then
1956 WBI ("extern int __gnat_handler_installed;");
1957 WBI ("");
1958 end if;
1960 -- Write argv/argc stuff if main program case
1962 if Bind_Main_Program then
1964 -- In the normal case, these are in the runtime library
1966 if not No_Run_Time_Specified then
1967 WBI ("extern int gnat_argc;");
1968 WBI ("extern char **gnat_argv;");
1969 WBI ("extern char **gnat_envp;");
1970 WBI ("extern int gnat_exit_status;");
1972 -- In the No_Run_Time case, they are right in the binder file
1973 -- and we initialize gnat_exit_status in the declaration.
1975 else
1976 WBI ("int gnat_argc;");
1977 WBI ("char **gnat_argv;");
1978 WBI ("char **gnat_envp;");
1979 WBI ("int gnat_exit_status = 0;");
1980 end if;
1982 WBI ("");
1983 end if;
1985 -- In no run-time mode, the __gnat_break_start routine (for the
1986 -- debugger to get initial control) is defined in this file.
1988 if No_Run_Time_Specified then
1989 WBI ("");
1990 WBI ("void __gnat_break_start () {}");
1991 end if;
1993 -- Generate the __gnat_version info only for the main program.
1994 -- Otherwise, it can lead under some circumstances to a symbol
1995 -- duplication during the link (for instance when a C program
1996 -- uses 2 Ada libraries)
1998 if Bind_Main_Program then
1999 WBI ("");
2000 WBI ("char __gnat_version[] = ""GNAT Version: " &
2001 Gnat_Version_String & """;");
2002 end if;
2004 -- Generate the adafinal routine. In no runtime mode, this is
2005 -- not needed, since there is no finalization to do.
2007 if not No_Run_Time_Specified then
2008 Gen_Adafinal_C;
2009 end if;
2011 Gen_Adainit_C;
2013 -- Main is only present for Ada main case
2015 if Bind_Main_Program then
2016 Gen_Main_C;
2017 end if;
2019 -- Scalar values, versions and object files needed in both cases
2021 if Initialize_Scalars_Used then
2022 Gen_Scalar_Values;
2023 end if;
2025 Gen_Versions_C;
2026 Gen_Elab_Order_C;
2027 Gen_Object_Files_Options;
2029 -- C binder output is complete
2031 Close_Binder_Output;
2032 end Gen_Output_File_C;
2034 -----------------------
2035 -- Gen_Scalar_Values --
2036 -----------------------
2038 procedure Gen_Scalar_Values is
2040 -- Strings to hold hex values of initialization constants. Note that
2041 -- we store these strings in big endian order, but they are actually
2042 -- used to initialize integer values, so the actual generated data
2043 -- will automaticaly have the right endianess.
2045 IS_Is1 : String (1 .. 2);
2046 IS_Is2 : String (1 .. 4);
2047 IS_Is4 : String (1 .. 8);
2048 IS_Is8 : String (1 .. 16);
2049 IS_Iu1 : String (1 .. 2);
2050 IS_Iu2 : String (1 .. 4);
2051 IS_Iu4 : String (1 .. 8);
2052 IS_Iu8 : String (1 .. 16);
2053 IS_Isf : String (1 .. 8);
2054 IS_Ifl : String (1 .. 8);
2055 IS_Ilf : String (1 .. 16);
2057 -- The string for Long_Long_Float is special. This is used only on the
2058 -- ia32 with 80-bit extended float (stored in 96 bits by gcc). The
2059 -- value here is represented little-endian, since that's the only way
2060 -- it is ever generated (this is not used on big-endian machines.
2062 IS_Ill : String (1 .. 24);
2064 begin
2065 -- -Sin (invalid values)
2067 if Opt.Initialize_Scalars_Mode = 'I' then
2068 IS_Is1 := "80";
2069 IS_Is2 := "8000";
2070 IS_Is4 := "80000000";
2071 IS_Is8 := "8000000000000000";
2072 IS_Iu1 := "FF";
2073 IS_Iu2 := "FFFF";
2074 IS_Iu4 := "FFFFFFFF";
2075 IS_Iu8 := "FFFFFFFFFFFFFFFF";
2076 IS_Isf := IS_Iu4;
2077 IS_Ifl := IS_Iu4;
2078 IS_Ilf := IS_Iu8;
2079 IS_Ill := "00000000000000C0FFFF0000";
2081 -- -Slo (low values)
2083 elsif Opt.Initialize_Scalars_Mode = 'L' then
2084 IS_Is1 := "80";
2085 IS_Is2 := "8000";
2086 IS_Is4 := "80000000";
2087 IS_Is8 := "8000000000000000";
2088 IS_Iu1 := "00";
2089 IS_Iu2 := "0000";
2090 IS_Iu4 := "00000000";
2091 IS_Iu8 := "0000000000000000";
2092 IS_Isf := "FF800000";
2093 IS_Ifl := IS_Isf;
2094 IS_Ilf := "FFF0000000000000";
2095 IS_Ill := "0000000000000080FFFF0000";
2097 -- -Shi (high values)
2099 elsif Opt.Initialize_Scalars_Mode = 'H' then
2100 IS_Is1 := "7F";
2101 IS_Is2 := "7FFF";
2102 IS_Is4 := "7FFFFFFF";
2103 IS_Is8 := "7FFFFFFFFFFFFFFF";
2104 IS_Iu1 := "FF";
2105 IS_Iu2 := "FFFF";
2106 IS_Iu4 := "FFFFFFFF";
2107 IS_Iu8 := "FFFFFFFFFFFFFFFF";
2108 IS_Isf := "7F800000";
2109 IS_Ifl := IS_Isf;
2110 IS_Ilf := "7FF0000000000000";
2111 IS_Ill := "0000000000000080FF7F0000";
2113 -- -Shh (hex byte)
2115 else pragma Assert (Opt.Initialize_Scalars_Mode = 'X');
2116 IS_Is1 (1 .. 2) := Opt.Initialize_Scalars_Val;
2117 IS_Is2 (1 .. 2) := Opt.Initialize_Scalars_Val;
2118 IS_Is2 (3 .. 4) := Opt.Initialize_Scalars_Val;
2120 for J in 1 .. 4 loop
2121 IS_Is4 (2 * J - 1 .. 2 * J) := Opt.Initialize_Scalars_Val;
2122 end loop;
2124 for J in 1 .. 8 loop
2125 IS_Is8 (2 * J - 1 .. 2 * J) := Opt.Initialize_Scalars_Val;
2126 end loop;
2128 IS_Iu1 := IS_Is1;
2129 IS_Iu2 := IS_Is2;
2130 IS_Iu4 := IS_Is4;
2131 IS_Iu8 := IS_Is8;
2133 IS_Isf := IS_Is4;
2134 IS_Ifl := IS_Is4;
2135 IS_Ilf := IS_Is8;
2137 for J in 1 .. 12 loop
2138 IS_Ill (2 * J - 1 .. 2 * J) := Opt.Initialize_Scalars_Val;
2139 end loop;
2140 end if;
2142 -- Generate output, Ada case
2144 if Ada_Bind_File then
2145 WBI ("");
2147 Set_String (" IS_Is1 : constant System.Scalar_Values.Byte1 := 16#");
2148 Set_String (IS_Is1);
2149 Write_Statement_Buffer ("#;");
2151 Set_String (" IS_Is2 : constant System.Scalar_Values.Byte2 := 16#");
2152 Set_String (IS_Is2);
2153 Write_Statement_Buffer ("#;");
2155 Set_String (" IS_Is4 : constant System.Scalar_Values.Byte4 := 16#");
2156 Set_String (IS_Is4);
2157 Write_Statement_Buffer ("#;");
2159 Set_String (" IS_Is8 : constant System.Scalar_Values.Byte8 := 16#");
2160 Set_String (IS_Is8);
2161 Write_Statement_Buffer ("#;");
2163 Set_String (" IS_Iu1 : constant System.Scalar_Values.Byte1 := 16#");
2164 Set_String (IS_Iu1);
2165 Write_Statement_Buffer ("#;");
2167 Set_String (" IS_Iu2 : constant System.Scalar_Values.Byte2 := 16#");
2168 Set_String (IS_Iu2);
2169 Write_Statement_Buffer ("#;");
2171 Set_String (" IS_Iu4 : constant System.Scalar_Values.Byte4 := 16#");
2172 Set_String (IS_Iu4);
2173 Write_Statement_Buffer ("#;");
2175 Set_String (" IS_Iu8 : constant System.Scalar_Values.Byte8 := 16#");
2176 Set_String (IS_Iu8);
2177 Write_Statement_Buffer ("#;");
2179 Set_String (" IS_Isf : constant System.Scalar_Values.Byte4 := 16#");
2180 Set_String (IS_Isf);
2181 Write_Statement_Buffer ("#;");
2183 Set_String (" IS_Ifl : constant System.Scalar_Values.Byte4 := 16#");
2184 Set_String (IS_Ifl);
2185 Write_Statement_Buffer ("#;");
2187 Set_String (" IS_Ilf : constant System.Scalar_Values.Byte8 := 16#");
2188 Set_String (IS_Ilf);
2189 Write_Statement_Buffer ("#;");
2191 -- Special case of Long_Long_Float. This is a 10-byte value used
2192 -- only on the x86. We could omit it for other architectures, but
2193 -- we don't easily have that kind of target specialization in the
2194 -- binder, and it's only 10 bytes, and only if -Sxx is used. Note
2195 -- that for architectures where Long_Long_Float is the same as
2196 -- Long_Float, the expander uses the Long_Float constant for the
2197 -- initializations of Long_Long_Float values.
2199 WBI (" IS_Ill : constant array (1 .. 12) of");
2200 WBI (" System.Scalar_Values.Byte1 := (");
2201 Set_String (" ");
2203 for J in 1 .. 6 loop
2204 Set_String (" 16#");
2205 Set_Char (IS_Ill (2 * J - 1));
2206 Set_Char (IS_Ill (2 * J));
2207 Set_String ("#,");
2208 end loop;
2210 Write_Statement_Buffer;
2211 Set_String (" ");
2213 for J in 7 .. 12 loop
2214 Set_String (" 16#");
2215 Set_Char (IS_Ill (2 * J - 1));
2216 Set_Char (IS_Ill (2 * J));
2218 if J = 12 then
2219 Set_String ("#);");
2220 else
2221 Set_String ("#,");
2222 end if;
2223 end loop;
2225 Write_Statement_Buffer;
2227 -- Output export statements to export to System.Scalar_Values
2229 WBI ("");
2231 WBI (" pragma Export (Ada, IS_Is1, ""__gnat_Is1"");");
2232 WBI (" pragma Export (Ada, IS_Is2, ""__gnat_Is2"");");
2233 WBI (" pragma Export (Ada, IS_Is4, ""__gnat_Is4"");");
2234 WBI (" pragma Export (Ada, IS_Is8, ""__gnat_Is8"");");
2235 WBI (" pragma Export (Ada, IS_Iu1, ""__gnat_Iu1"");");
2236 WBI (" pragma Export (Ada, IS_Iu2, ""__gnat_Iu2"");");
2237 WBI (" pragma Export (Ada, IS_Iu4, ""__gnat_Iu4"");");
2238 WBI (" pragma Export (Ada, IS_Iu8, ""__gnat_Iu8"");");
2239 WBI (" pragma Export (Ada, IS_Isf, ""__gnat_Isf"");");
2240 WBI (" pragma Export (Ada, IS_Ifl, ""__gnat_Ifl"");");
2241 WBI (" pragma Export (Ada, IS_Ilf, ""__gnat_Ilf"");");
2242 WBI (" pragma Export (Ada, IS_Ill, ""__gnat_Ill"");");
2244 -- Generate output C case
2246 else
2247 -- The lines we generate in this case are of the form
2248 -- typ __gnat_I?? = 0x??;
2249 -- where typ is appropriate to the length
2251 WBI ("");
2253 Set_String ("unsigned char __gnat_Is1 = 0x");
2254 Set_String (IS_Is1);
2255 Write_Statement_Buffer (";");
2257 Set_String ("unsigned short __gnat_Is2 = 0x");
2258 Set_String (IS_Is2);
2259 Write_Statement_Buffer (";");
2261 Set_String ("unsigned __gnat_Is4 = 0x");
2262 Set_String (IS_Is4);
2263 Write_Statement_Buffer (";");
2265 Set_String ("long long unsigned __gnat_Is8 = 0x");
2266 Set_String (IS_Is8);
2267 Write_Statement_Buffer ("LL;");
2269 Set_String ("unsigned char __gnat_Iu1 = 0x");
2270 Set_String (IS_Is1);
2271 Write_Statement_Buffer (";");
2273 Set_String ("unsigned short __gnat_Iu2 = 0x");
2274 Set_String (IS_Is2);
2275 Write_Statement_Buffer (";");
2277 Set_String ("unsigned __gnat_Iu4 = 0x");
2278 Set_String (IS_Is4);
2279 Write_Statement_Buffer (";");
2281 Set_String ("long long unsigned __gnat_Iu8 = 0x");
2282 Set_String (IS_Is8);
2283 Write_Statement_Buffer ("LL;");
2285 Set_String ("unsigned __gnat_Isf = 0x");
2286 Set_String (IS_Isf);
2287 Write_Statement_Buffer (";");
2289 Set_String ("unsigned __gnat_Ifl = 0x");
2290 Set_String (IS_Ifl);
2291 Write_Statement_Buffer (";");
2293 Set_String ("long long unsigned __gnat_Ilf = 0x");
2294 Set_String (IS_Ilf);
2295 Write_Statement_Buffer ("LL;");
2297 -- For Long_Long_Float, we generate
2298 -- char __gnat_Ill[12] = {0x??, 0x??, 0x??, 0x??, 0x??, 0x??,
2299 -- 0x??, 0x??, 0x??, 0x??, 0x??, 0x??);
2301 Set_String ("unsigned char __gnat_Ill[12] = {");
2303 for J in 1 .. 6 loop
2304 Set_String ("0x");
2305 Set_Char (IS_Ill (2 * J - 1));
2306 Set_Char (IS_Ill (2 * J));
2307 Set_String (", ");
2308 end loop;
2310 Write_Statement_Buffer;
2311 Set_String (" ");
2313 for J in 7 .. 12 loop
2314 Set_String ("0x");
2315 Set_Char (IS_Ill (2 * J - 1));
2316 Set_Char (IS_Ill (2 * J));
2318 if J = 12 then
2319 Set_String ("};");
2320 else
2321 Set_String (", ");
2322 end if;
2323 end loop;
2325 Write_Statement_Buffer;
2326 end if;
2327 end Gen_Scalar_Values;
2329 ----------------------
2330 -- Gen_Versions_Ada --
2331 ----------------------
2333 -- This routine generates two sets of lines. The first set has the form:
2335 -- unnnnn : constant Integer := 16#hhhhhhhh#;
2337 -- The second set has the form
2339 -- pragma Export (C, unnnnn, unam);
2341 -- for each unit, where unam is the unit name suffixed by either B or
2342 -- S for body or spec, with dots replaced by double underscores, and
2343 -- hhhhhhhh is the version number, and nnnnn is a 5-digits serial number.
2345 procedure Gen_Versions_Ada is
2346 Ubuf : String (1 .. 6) := "u00000";
2348 procedure Increment_Ubuf;
2349 -- Little procedure to increment the serial number
2351 procedure Increment_Ubuf is
2352 begin
2353 for J in reverse Ubuf'Range loop
2354 Ubuf (J) := Character'Succ (Ubuf (J));
2355 exit when Ubuf (J) <= '9';
2356 Ubuf (J) := '0';
2357 end loop;
2358 end Increment_Ubuf;
2360 -- Start of processing for Gen_Versions_Ada
2362 begin
2363 if Bind_For_Library then
2365 -- When building libraries, the version number of each unit can
2366 -- not be computed, since the binder does not know the full list
2367 -- of units. Therefore, the 'Version and 'Body_Version
2368 -- attributes can not supported in this case.
2370 return;
2371 end if;
2373 WBI ("");
2375 WBI (" type Version_32 is mod 2 ** 32;");
2376 for U in Units.First .. Units.Last loop
2377 Increment_Ubuf;
2378 WBI (" " & Ubuf & " : constant Version_32 := 16#" &
2379 Units.Table (U).Version & "#;");
2380 end loop;
2382 WBI ("");
2383 Ubuf := "u00000";
2385 for U in Units.First .. Units.Last loop
2386 Increment_Ubuf;
2387 Set_String (" pragma Export (C, ");
2388 Set_String (Ubuf);
2389 Set_String (", """);
2391 Get_Name_String (Units.Table (U).Uname);
2393 for K in 1 .. Name_Len loop
2394 if Name_Buffer (K) = '.' then
2395 Set_Char ('_');
2396 Set_Char ('_');
2398 elsif Name_Buffer (K) = '%' then
2399 exit;
2401 else
2402 Set_Char (Name_Buffer (K));
2403 end if;
2404 end loop;
2406 if Name_Buffer (Name_Len) = 's' then
2407 Set_Char ('S');
2408 else
2409 Set_Char ('B');
2410 end if;
2412 Set_String (""");");
2413 Write_Statement_Buffer;
2414 end loop;
2416 end Gen_Versions_Ada;
2418 --------------------
2419 -- Gen_Versions_C --
2420 --------------------
2422 -- This routine generates a line of the form:
2424 -- unsigned unam = 0xhhhhhhhh;
2426 -- for each unit, where unam is the unit name suffixed by either B or
2427 -- S for body or spec, with dots replaced by double underscores.
2429 procedure Gen_Versions_C is
2430 begin
2431 if Bind_For_Library then
2433 -- When building libraries, the version number of each unit can
2434 -- not be computed, since the binder does not know the full list
2435 -- of units. Therefore, the 'Version and 'Body_Version
2436 -- attributes can not supported.
2438 return;
2439 end if;
2441 for U in Units.First .. Units.Last loop
2442 Set_String ("unsigned ");
2444 Get_Name_String (Units.Table (U).Uname);
2446 for K in 1 .. Name_Len loop
2447 if Name_Buffer (K) = '.' then
2448 Set_String ("__");
2450 elsif Name_Buffer (K) = '%' then
2451 exit;
2453 else
2454 Set_Char (Name_Buffer (K));
2455 end if;
2456 end loop;
2458 if Name_Buffer (Name_Len) = 's' then
2459 Set_Char ('S');
2460 else
2461 Set_Char ('B');
2462 end if;
2464 Set_String (" = 0x");
2465 Set_String (Units.Table (U).Version);
2466 Set_Char (';');
2467 Write_Statement_Buffer;
2468 end loop;
2470 end Gen_Versions_C;
2472 -----------------------
2473 -- Get_Ada_Main_Name --
2474 -----------------------
2476 function Get_Ada_Main_Name return String is
2477 Suffix : constant String := "_00";
2478 Name : String (1 .. Opt.Ada_Main_Name.all'Length + Suffix'Length) :=
2479 Opt.Ada_Main_Name.all & Suffix;
2480 Nlen : Natural;
2482 begin
2483 -- The main program generated by JGNAT expects a package called
2484 -- ada_<main procedure>.
2486 if Hostparm.Java_VM then
2487 -- Get main program name
2489 Get_Name_String (Units.Table (First_Unit_Entry).Uname);
2491 -- Remove the %b
2493 return "ada_" & Name_Buffer (1 .. Name_Len - 2);
2494 end if;
2496 -- This loop tries the following possibilities in order
2497 -- <Ada_Main>
2498 -- <Ada_Main>_01
2499 -- <Ada_Main>_02
2500 -- ..
2501 -- <Ada_Main>_99
2502 -- where <Ada_Main> is equal to Opt.Ada_Main_Name. By default,
2503 -- it is set to 'ada_main'.
2505 for J in 0 .. 99 loop
2506 if J = 0 then
2507 Nlen := Name'Length - Suffix'Length;
2508 else
2509 Nlen := Name'Length;
2510 Name (Name'Last) := Character'Val (J mod 10 + Character'Pos ('0'));
2511 Name (Name'Last - 1) :=
2512 Character'Val (J / 10 + Character'Pos ('0'));
2513 end if;
2515 for K in ALIs.First .. ALIs.Last loop
2516 for L in ALIs.Table (K).First_Unit .. ALIs.Table (K).Last_Unit loop
2518 -- Get unit name, removing %b or %e at end
2520 Get_Name_String (Units.Table (L).Uname);
2521 Name_Len := Name_Len - 2;
2523 if Name_Buffer (1 .. Name_Len) = Name (1 .. Nlen) then
2524 goto Continue;
2525 end if;
2526 end loop;
2527 end loop;
2529 return Name (1 .. Nlen);
2531 <<Continue>>
2532 null;
2533 end loop;
2535 -- If we fall through, just use a peculiar unlikely name
2537 return ("Qwertyuiop");
2538 end Get_Ada_Main_Name;
2540 -------------------
2541 -- Get_Main_Name --
2542 -------------------
2544 function Get_Main_Name return String is
2545 Target : constant String_Ptr := Target_Name;
2546 VxWorks_Target : constant Boolean :=
2547 Target (Target'Last - 7 .. Target'Last) = "vxworks/";
2549 begin
2550 -- Explicit name given with -M switch
2552 if Bind_Alternate_Main_Name then
2553 return Alternate_Main_Name.all;
2555 -- Case of main program name to be used directly
2557 elsif VxWorks_Target then
2559 -- Get main program name
2561 Get_Name_String (Units.Table (First_Unit_Entry).Uname);
2563 -- If this is a child name, return only the name of the child,
2564 -- since we can't have dots in a nested program name. Note that
2565 -- we do not include the %b at the end of the unit name.
2567 for J in reverse 1 .. Name_Len - 3 loop
2568 if J = 1 or else Name_Buffer (J - 1) = '.' then
2569 return Name_Buffer (J .. Name_Len - 2);
2570 end if;
2571 end loop;
2573 raise Program_Error; -- impossible exit
2575 -- Case where "main" is to be used as default
2577 else
2578 return "main";
2579 end if;
2580 end Get_Main_Name;
2582 ----------------------
2583 -- Lt_Linker_Option --
2584 ----------------------
2586 function Lt_Linker_Option (Op1, Op2 : Natural) return Boolean is
2587 begin
2588 if Linker_Options.Table (Op1).Internal_File
2590 Linker_Options.Table (Op2).Internal_File
2591 then
2592 return Linker_Options.Table (Op1).Internal_File
2594 Linker_Options.Table (Op2).Internal_File;
2595 else
2596 if Units.Table (Linker_Options.Table (Op1).Unit).Elab_Position
2598 Units.Table (Linker_Options.Table (Op2).Unit).Elab_Position
2599 then
2600 return Units.Table (Linker_Options.Table (Op1).Unit).Elab_Position
2602 Units.Table (Linker_Options.Table (Op2).Unit).Elab_Position;
2604 else
2605 return Linker_Options.Table (Op1).Original_Pos
2607 Linker_Options.Table (Op2).Original_Pos;
2608 end if;
2609 end if;
2610 end Lt_Linker_Option;
2612 ------------------------
2613 -- Move_Linker_Option --
2614 ------------------------
2616 procedure Move_Linker_Option (From : Natural; To : Natural) is
2617 begin
2618 Linker_Options.Table (To) := Linker_Options.Table (From);
2619 end Move_Linker_Option;
2621 ----------------------------
2622 -- Public_Version_Warning --
2623 ----------------------------
2625 procedure Public_Version_Warning is
2627 Time : Int := Time_From_Last_Bind;
2629 -- Constants to help defining periods
2631 Hour : constant := 60;
2632 Day : constant := 24 * Hour;
2634 Never : constant := Integer'Last;
2635 -- Special value indicating no warnings should be given
2637 -- Constants defining when the warning is issued. Programs with more
2638 -- than Large Units will issue a warning every Period_Large amount of
2639 -- time. Smaller programs will generate a warning every Period_Small
2640 -- amount of time.
2642 Large : constant := 20;
2643 -- Threshold for considering a program small or large
2645 Period_Large : constant := Day;
2646 -- Periodic warning time for large programs
2648 Period_Small : constant := Never;
2649 -- Periodic warning time for small programs
2651 Nb_Unit : Int;
2653 begin
2654 -- Compute the number of units that are not GNAT internal files
2656 Nb_Unit := 0;
2657 for A in ALIs.First .. ALIs.Last loop
2658 if not Is_Internal_File_Name (ALIs.Table (A).Sfile) then
2659 Nb_Unit := Nb_Unit + 1;
2660 end if;
2661 end loop;
2663 -- Do not emit the message if the last message was emitted in the
2664 -- specified period taking into account the number of units.
2666 if Nb_Unit < Large and then Time <= Period_Small then
2667 return;
2669 elsif Time <= Period_Large then
2670 return;
2671 end if;
2673 Write_Eol;
2674 Write_Str ("IMPORTANT NOTICE:");
2675 Write_Eol;
2676 Write_Str (" This version of GNAT is unsupported"
2677 & " and comes with absolutely no warranty.");
2678 Write_Eol;
2679 Write_Str (" If you intend to evaluate or use GNAT for building "
2680 & "commercial applications,");
2681 Write_Eol;
2682 Write_Str (" please consult http://www.gnat.com/ for information");
2683 Write_Eol;
2684 Write_Str (" on the GNAT Professional product line.");
2685 Write_Eol;
2686 Write_Eol;
2687 end Public_Version_Warning;
2689 ----------------------------
2690 -- Resolve_Binder_Options --
2691 ----------------------------
2693 procedure Resolve_Binder_Options is
2694 begin
2695 for E in Elab_Order.First .. Elab_Order.Last loop
2696 Get_Name_String (Units.Table (Elab_Order.Table (E)).Uname);
2698 -- The procedure of looking for specific packages and setting
2699 -- flags is very wrong, but there isn't a good alternative at
2700 -- this time.
2702 if Name_Buffer (1 .. 19) = "system.os_interface" then
2703 With_GNARL := True;
2704 end if;
2706 if Hostparm.OpenVMS and then Name_Buffer (1 .. 3) = "dec" then
2707 With_DECGNAT := True;
2708 end if;
2709 end loop;
2710 end Resolve_Binder_Options;
2712 --------------
2713 -- Set_Char --
2714 --------------
2716 procedure Set_Char (C : Character) is
2717 begin
2718 Last := Last + 1;
2719 Statement_Buffer (Last) := C;
2720 end Set_Char;
2722 -------------
2723 -- Set_Int --
2724 -------------
2726 procedure Set_Int (N : Int) is
2727 begin
2728 if N < 0 then
2729 Set_String ("-");
2730 Set_Int (-N);
2732 else
2733 if N > 9 then
2734 Set_Int (N / 10);
2735 end if;
2737 Last := Last + 1;
2738 Statement_Buffer (Last) :=
2739 Character'Val (N mod 10 + Character'Pos ('0'));
2740 end if;
2741 end Set_Int;
2743 ---------------------------
2744 -- Set_Main_Program_Name --
2745 ---------------------------
2747 procedure Set_Main_Program_Name is
2748 begin
2749 -- Note that name has %b on the end which we ignore
2751 -- First we output the initial _ada_ since we know that the main
2752 -- program is a library level subprogram.
2754 Set_String ("_ada_");
2756 -- Copy name, changing dots to double underscores
2758 for J in 1 .. Name_Len - 2 loop
2759 if Name_Buffer (J) = '.' then
2760 Set_String ("__");
2761 else
2762 Set_Char (Name_Buffer (J));
2763 end if;
2764 end loop;
2765 end Set_Main_Program_Name;
2767 ---------------------
2768 -- Set_Name_Buffer --
2769 ---------------------
2771 procedure Set_Name_Buffer is
2772 begin
2773 for J in 1 .. Name_Len loop
2774 Set_Char (Name_Buffer (J));
2775 end loop;
2776 end Set_Name_Buffer;
2778 ----------------
2779 -- Set_String --
2780 ----------------
2782 procedure Set_String (S : String) is
2783 begin
2784 Statement_Buffer (Last + 1 .. Last + S'Length) := S;
2785 Last := Last + S'Length;
2786 end Set_String;
2788 -------------------
2789 -- Set_Unit_Name --
2790 -------------------
2792 procedure Set_Unit_Name is
2793 begin
2794 for J in 1 .. Name_Len - 2 loop
2795 if Name_Buffer (J) /= '.' then
2796 Set_Char (Name_Buffer (J));
2797 else
2798 Set_String ("__");
2799 end if;
2800 end loop;
2801 end Set_Unit_Name;
2803 ---------------------
2804 -- Set_Unit_Number --
2805 ---------------------
2807 procedure Set_Unit_Number (U : Unit_Id) is
2808 Num_Units : constant Nat := Nat (Units.Table'Last) - Nat (Unit_Id'First);
2809 Unum : constant Nat := Nat (U) - Nat (Unit_Id'First);
2811 begin
2812 if Num_Units >= 10 and then Unum < 10 then
2813 Set_Char ('0');
2814 end if;
2816 if Num_Units >= 100 and then Unum < 100 then
2817 Set_Char ('0');
2818 end if;
2820 Set_Int (Unum);
2821 end Set_Unit_Number;
2823 ------------
2824 -- Tab_To --
2825 ------------
2827 procedure Tab_To (N : Natural) is
2828 begin
2829 while Last < N loop
2830 Set_Char (' ');
2831 end loop;
2832 end Tab_To;
2834 -----------
2835 -- Value --
2836 -----------
2838 function Value (chars : chars_ptr) return String is
2839 function Strlen (chars : chars_ptr) return Natural;
2840 pragma Import (C, Strlen);
2842 begin
2843 if chars = Null_Address then
2844 return "";
2846 else
2847 declare
2848 subtype Result_Type is String (1 .. Strlen (chars));
2850 Result : Result_Type;
2851 for Result'Address use chars;
2853 begin
2854 return Result;
2855 end;
2856 end if;
2857 end Value;
2859 ----------------------
2860 -- Write_Info_Ada_C --
2861 ----------------------
2863 procedure Write_Info_Ada_C (Ada : String; C : String; Common : String) is
2864 begin
2865 if Ada_Bind_File then
2866 declare
2867 S : String (1 .. Ada'Length + Common'Length);
2869 begin
2870 S (1 .. Ada'Length) := Ada;
2871 S (Ada'Length + 1 .. S'Length) := Common;
2872 WBI (S);
2873 end;
2875 else
2876 declare
2877 S : String (1 .. C'Length + Common'Length);
2879 begin
2880 S (1 .. C'Length) := C;
2881 S (C'Length + 1 .. S'Length) := Common;
2882 WBI (S);
2883 end;
2884 end if;
2885 end Write_Info_Ada_C;
2887 ----------------------------
2888 -- Write_Statement_Buffer --
2889 ----------------------------
2891 procedure Write_Statement_Buffer is
2892 begin
2893 WBI (Statement_Buffer (1 .. Last));
2894 Last := 0;
2895 end Write_Statement_Buffer;
2897 procedure Write_Statement_Buffer (S : String) is
2898 begin
2899 Set_String (S);
2900 Write_Statement_Buffer;
2901 end Write_Statement_Buffer;
2903 end Bindgen;