1------------------------------------------------------------------------------
2--                                                                          --
3--                         GNAT COMPILER COMPONENTS                         --
4--                                                                          --
5--                              B I N D G E N                               --
6--                                                                          --
7--                                 B o d y                                  --
8--                                                                          --
9--          Copyright (C) 1992-2019, 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 ALI;      use ALI;
27with Casing;   use Casing;
28with Fname;    use Fname;
29with Gnatvsn;  use Gnatvsn;
30with Hostparm;
31with Namet;    use Namet;
32with Opt;      use Opt;
33with Osint;    use Osint;
34with Osint.B;  use Osint.B;
35with Output;   use Output;
36with Rident;   use Rident;
37with Stringt;  use Stringt;
38with Table;
39with Targparm; use Targparm;
40with Types;    use Types;
41
42with System.OS_Lib;
43with System.WCh_Con; use System.WCh_Con;
44
45with GNAT.Heap_Sort_A; use GNAT.Heap_Sort_A;
46with GNAT.HTable;
47
48package body Bindgen is
49   Statement_Buffer : String (1 .. 1000);
50   --  Buffer used for constructing output statements
51
52   Stm_Last : Natural := 0;
53   --  Stm_Last location in Statement_Buffer currently set
54
55   With_GNARL : Boolean := False;
56   --  Flag which indicates whether the program uses the GNARL library
57   --  (presence of the unit System.OS_Interface)
58
59   Num_Elab_Calls : Nat := 0;
60   --  Number of generated calls to elaboration routines
61
62   Num_Primary_Stacks : Int := 0;
63   --  Number of default-sized primary stacks the binder needs to allocate for
64   --  task objects declared in the program.
65
66   Num_Sec_Stacks : Int := 0;
67   --  Number of default-sized primary stacks the binder needs to allocate for
68   --  task objects declared in the program.
69
70   System_Restrictions_Used : Boolean := False;
71   --  Flag indicating whether the unit System.Restrictions is in the closure
72   --  of the partition. This is set by Resolve_Binder_Options, and is used
73   --  to determine whether or not to initialize the restrictions information
74   --  in the body of the binder generated file (we do not want to do this
75   --  unconditionally, since it drags in the System.Restrictions unit
76   --  unconditionally, which is unpleasand, especially for ZFP etc.)
77
78   Dispatching_Domains_Used : Boolean := False;
79   --  Flag indicating whether multiprocessor dispatching domains are used in
80   --  the closure of the partition. This is set by Resolve_Binder_Options, and
81   --  is used to call the routine to disallow the creation of new dispatching
82   --  domains just before calling the main procedure from the environment
83   --  task.
84
85   System_Secondary_Stack_Used : Boolean := False;
86   --  Flag indicating whether the unit System.Secondary_Stack is in the
87   --  closure of the partition. This is set by Resolve_Binder_Options, and
88   --  is used to initialize the package in cases where the run-time brings
89   --  in package but the secondary stack is not used.
90
91   System_Tasking_Restricted_Stages_Used : Boolean := False;
92   --  Flag indicating whether the unit System.Tasking.Restricted.Stages is in
93   --  the closure of the partition. This is set by Resolve_Binder_Options,
94   --  and it used to call a routine to active all the tasks at the end of
95   --  the elaboration when partition elaboration policy is sequential.
96
97   System_Interrupts_Used : Boolean := False;
98   --  Flag indicating whether the unit System.Interrups is in the closure of
99   --  the partition. This is set by Resolve_Binder_Options, and it used to
100   --  attach interrupt handlers at the end of the elaboration when partition
101   --  elaboration policy is sequential.
102
103   System_BB_CPU_Primitives_Multiprocessors_Used : Boolean := False;
104   --  Flag indicating whether unit System.BB.CPU_Primitives.Multiprocessors
105   --  is in the closure of the partition. This is set by procedure
106   --  Resolve_Binder_Options, and it is used to call a procedure that starts
107   --  slave processors.
108
109   System_Version_Control_Used : Boolean := False;
110   --  Flag indicating whether unit System.Version_Control is in the closure.
111   --  This unit is implicitly withed by the compiler when Version or
112   --  Body_Version attributes are used. If the package is not in the closure,
113   --  the version definitions can be removed.
114
115   Lib_Final_Built : Boolean := False;
116   --  Flag indicating whether the finalize_library rountine has been built
117
118   Bind_Env_String_Built : Boolean := False;
119   --  Flag indicating whether a bind environment string has been built
120
121   CodePeer_Wrapper_Name : constant String := "call_main_subprogram";
122   --  For CodePeer, introduce a wrapper subprogram which calls the
123   --  user-defined main subprogram.
124
125   ----------------------------------
126   -- Interface_State Pragma Table --
127   ----------------------------------
128
129   --  This table assembles the interface state pragma information from
130   --  all the units in the partition. Note that Bcheck has already checked
131   --  that the information is consistent across units. The entries
132   --  in this table are n/u/r/s for not set/user/runtime/system.
133
134   package IS_Pragma_Settings is new Table.Table
135     (Table_Component_Type => Character,
136      Table_Index_Type     => Int,
137      Table_Low_Bound      => 0,
138      Table_Initial        => 100,
139      Table_Increment      => 200,
140      Table_Name           => "IS_Pragma_Settings");
141
142   --  This table assembles the Priority_Specific_Dispatching pragma
143   --  information from all the units in the partition. Note that Bcheck has
144   --  already checked that the information is consistent across units.
145   --  The entries in this table are the upper case first character of the
146   --  policy name, e.g. 'F' for FIFO_Within_Priorities.
147
148   package PSD_Pragma_Settings is new Table.Table
149     (Table_Component_Type => Character,
150      Table_Index_Type     => Int,
151      Table_Low_Bound      => 0,
152      Table_Initial        => 100,
153      Table_Increment      => 200,
154      Table_Name           => "PSD_Pragma_Settings");
155
156   ----------------------------
157   -- Bind_Environment Table --
158   ----------------------------
159
160   subtype Header_Num is Int range 0 .. 36;
161
162   function Hash (Nam : Name_Id) return Header_Num;
163
164   package Bind_Environment is new GNAT.HTable.Simple_HTable
165     (Header_Num => Header_Num,
166      Element    => Name_Id,
167      No_Element => No_Name,
168      Key        => Name_Id,
169      Hash       => Hash,
170      Equal      => "=");
171
172   ----------------------
173   -- Run-Time Globals --
174   ----------------------
175
176   --  This section documents the global variables that are set from the
177   --  generated binder file.
178
179   --     Main_Priority                 : Integer;
180   --     Time_Slice_Value              : Integer;
181   --     Heap_Size                     : Natural;
182   --     WC_Encoding                   : Character;
183   --     Locking_Policy                : Character;
184   --     Queuing_Policy                : Character;
185   --     Task_Dispatching_Policy       : Character;
186   --     Priority_Specific_Dispatching : System.Address;
187   --     Num_Specific_Dispatching      : Integer;
188   --     Restrictions                  : System.Address;
189   --     Interrupt_States              : System.Address;
190   --     Num_Interrupt_States          : Integer;
191   --     Unreserve_All_Interrupts      : Integer;
192   --     Exception_Tracebacks          : Integer;
193   --     Exception_Tracebacks_Symbolic : Integer;
194   --     Detect_Blocking               : Integer;
195   --     Default_Stack_Size            : Integer;
196   --     Default_Secondary_Stack_Size  : System.Parameters.Size_Type;
197   --     Leap_Seconds_Support          : Integer;
198   --     Main_CPU                      : Integer;
199   --     Default_Sized_SS_Pool         : System.Address;
200   --     Binder_Sec_Stacks_Count       : Natural;
201
202   --  Main_Priority is the priority value set by pragma Priority in the main
203   --  program. If no such pragma is present, the value is -1.
204
205   --  Time_Slice_Value is the time slice value set by pragma Time_Slice in the
206   --  main program, or by the use of a -Tnnn parameter for the binder (if both
207   --  are present, the binder value overrides). The value is in milliseconds.
208   --  A value of zero indicates that time slicing should be suppressed. If no
209   --  pragma is present, and no -T switch was used, the value is -1.
210
211   --  WC_Encoding shows the wide character encoding method used for the main
212   --  program. This is one of the encoding letters defined in
213   --  System.WCh_Con.WC_Encoding_Letters.
214
215   --  Locking_Policy is a space if no locking policy was specified for the
216   --  partition. If a locking policy was specified, the value is the upper
217   --  case first character of the locking policy name, for example, 'C' for
218   --  Ceiling_Locking.
219
220   --  Queuing_Policy is a space if no queuing policy was specified for the
221   --  partition. If a queuing policy was specified, the value is the upper
222   --  case first character of the queuing policy name for example, 'F' for
223   --  FIFO_Queuing.
224
225   --  Task_Dispatching_Policy is a space if no task dispatching policy was
226   --  specified for the partition. If a task dispatching policy was specified,
227   --  the value is the upper case first character of the policy name, e.g. 'F'
228   --  for FIFO_Within_Priorities.
229
230   --  Priority_Specific_Dispatching is the address of a string used to store
231   --  the task dispatching policy specified for the different priorities in
232   --  the partition. The length of this string is determined by the last
233   --  priority for which such a pragma applies (the string will be a null
234   --  string if no specific dispatching policies were used). If pragma were
235   --  present, the entries apply to the priorities in sequence from the first
236   --  priority. The value stored is the upper case first character of the
237   --  policy name, or 'F' (for FIFO_Within_Priorities) as the default value
238   --  for those priority ranges not specified.
239
240   --  Num_Specific_Dispatching is length of the Priority_Specific_Dispatching
241   --  string. It will be set to zero if no Priority_Specific_Dispatching
242   --  pragmas are present.
243
244   --  Restrictions is the address of a null-terminated string specifying the
245   --  restrictions information for the partition. The format is identical to
246   --  that of the parameter string found on R lines in ali files (see Lib.Writ
247   --  spec in lib-writ.ads for full details). The difference is that in this
248   --  context the values are the cumulative ones for the entire partition.
249
250   --  Interrupt_States is the address of a string used to specify the
251   --  cumulative results of Interrupt_State pragmas used in the partition.
252   --  The length of this string is determined by the last interrupt for which
253   --  such a pragma is given (the string will be a null string if no pragmas
254   --  were used). If pragma were present the entries apply to the interrupts
255   --  in sequence from the first interrupt, and are set to one of four
256   --  possible settings: 'n' for not specified, 'u' for user, 'r' for run
257   --  time, 's' for system, see description of Interrupt_State pragma for
258   --  further details.
259
260   --  Num_Interrupt_States is the length of the Interrupt_States string. It
261   --  will be set to zero if no Interrupt_State pragmas are present.
262
263   --  Unreserve_All_Interrupts is set to one if at least one unit in the
264   --  partition had a pragma Unreserve_All_Interrupts, and zero otherwise.
265
266   --  Exception_Tracebacks is set to one if the -Ea or -E parameter was
267   --  present in the bind and to zero otherwise. Note that on some targets
268   --  exception tracebacks are provided by default, so a value of zero for
269   --  this parameter does not necessarily mean no trace backs are available.
270
271   --  Exception_Tracebacks_Symbolic is set to one if the -Es parameter was
272   --  present in the bind and to zero otherwise.
273
274   --  Detect_Blocking indicates whether pragma Detect_Blocking is active or
275   --  not. A value of zero indicates that the pragma is not present, while a
276   --  value of 1 signals its presence in the partition.
277
278   --  Default_Stack_Size is the default stack size used when creating an Ada
279   --  task with no explicit Storage_Size clause.
280
281   --  Default_Secondary_Stack_Size is the default secondary stack size used
282   --  when creating an Ada task with no explicit Secondary_Stack_Size clause.
283
284   --  Leap_Seconds_Support denotes whether leap seconds have been enabled or
285   --  disabled. A value of zero indicates that leap seconds are turned "off",
286   --  while a value of one signifies "on" status.
287
288   --  Main_CPU is the processor set by pragma CPU in the main program. If no
289   --  such pragma is present, the value is -1.
290
291   --  Default_Sized_SS_Pool is set to the address of the default-sized
292   --  secondary stacks array generated by the binder. This pool of stacks is
293   --  generated when either the restriction No_Implicit_Heap_Allocations
294   --  or No_Implicit_Task_Allocations is active.
295
296   --  Binder_Sec_Stacks_Count is the number of generated secondary stacks in
297   --  the Default_Sized_SS_Pool.
298
299   procedure WBI (Info : String) renames Osint.B.Write_Binder_Info;
300   --  Convenient shorthand used throughout
301
302   -----------------------
303   -- Local Subprograms --
304   -----------------------
305
306   procedure Gen_Adainit (Elab_Order : Unit_Id_Array);
307   --  Generates the Adainit procedure
308
309   procedure Gen_Adafinal;
310   --  Generate the Adafinal procedure
311
312   procedure Gen_Bind_Env_String;
313   --  Generate the bind environment buffer
314
315   procedure Gen_CodePeer_Wrapper;
316   --  For CodePeer, generate wrapper which calls user-defined main subprogram
317
318   procedure Gen_Elab_Calls (Elab_Order : Unit_Id_Array);
319   --  Generate sequence of elaboration calls
320
321   procedure Gen_Elab_Externals (Elab_Order : Unit_Id_Array);
322   --  Generate sequence of external declarations for elaboration
323
324   procedure Gen_Elab_Order (Elab_Order : Unit_Id_Array);
325   --  Generate comments showing elaboration order chosen
326
327   procedure Gen_Finalize_Library (Elab_Order : Unit_Id_Array);
328   --  Generate a sequence of finalization calls to elaborated packages
329
330   procedure Gen_Main;
331   --  Generate procedure main
332
333   procedure Gen_Object_Files_Options (Elab_Order : Unit_Id_Array);
334   --  Output comments containing a list of the full names of the object
335   --  files to be linked and the list of linker options supplied by
336   --  Linker_Options pragmas in the source.
337
338   procedure Gen_Output_File_Ada
339     (Filename   : String;
340      Elab_Order : Unit_Id_Array);
341   --  Generate Ada output file
342
343   procedure Gen_Restrictions;
344   --  Generate initialization of restrictions variable
345
346   procedure Gen_Versions;
347   --  Output series of definitions for unit versions
348
349   function Get_Ada_Main_Name return String;
350   --  This function is used for the Ada main output to compute a usable name
351   --  for the generated main program. The normal main program name is
352   --  Ada_Main, but this won't work if the user has a unit with this name.
353   --  This function tries Ada_Main first, and if there is such a clash, then
354   --  it tries Ada_Name_01, Ada_Name_02 ... Ada_Name_99 in sequence.
355
356   function Get_Main_Unit_Name (S : String) return String;
357   --  Return the main unit name corresponding to S by replacing '.' with '_'
358
359   function Get_Main_Name return String;
360   --  This function is used in the main output case to compute the correct
361   --  external main program. It is "main" by default, unless the flag
362   --  Use_Ada_Main_Program_Name_On_Target is set, in which case it is the name
363   --  of the Ada main name without the "_ada". This default can be overridden
364   --  explicitly using the -Mname binder switch.
365
366   function Get_WC_Encoding return Character;
367   --  Return wide character encoding method to set as WC_Encoding in output.
368   --  If -W has been used, returns the specified encoding, otherwise returns
369   --  the encoding method used for the main program source. If there is no
370   --  main program source (-z switch used), returns brackets ('b').
371
372   function Has_Finalizer (Elab_Order : Unit_Id_Array) return Boolean;
373   --  Determine whether the current unit has at least one library-level
374   --  finalizer.
375
376   function Lt_Linker_Option (Op1 : Natural; Op2 : Natural) return Boolean;
377   --  Compare linker options, when sorting, first according to
378   --  Is_Internal_File (internal files come later) and then by
379   --  elaboration order position (latest to earliest).
380
381   procedure Move_Linker_Option (From : Natural; To : Natural);
382   --  Move routine for sorting linker options
383
384   procedure Resolve_Binder_Options (Elab_Order : Unit_Id_Array);
385   --  Set the value of With_GNARL
386
387   procedure Set_Char (C : Character);
388   --  Set given character in Statement_Buffer at the Stm_Last + 1 position
389   --  and increment Stm_Last by one to reflect the stored character.
390
391   procedure Set_Int (N : Int);
392   --  Set given value in decimal in Statement_Buffer with no spaces starting
393   --  at the Stm_Last + 1 position, and updating Stm_Last past the value. A
394   --  minus sign is output for a negative value.
395
396   procedure Set_Boolean (B : Boolean);
397   --  Set given boolean value in Statement_Buffer at the Stm_Last + 1 position
398   --  and update Stm_Last past the value.
399
400   procedure Set_IS_Pragma_Table;
401   --  Initializes contents of IS_Pragma_Settings table from ALI table
402
403   procedure Set_Main_Program_Name;
404   --  Given the main program name in Name_Buffer (length in Name_Len) generate
405   --  the name of the routine to be used in the call. The name is generated
406   --  starting at Stm_Last + 1, and Stm_Last is updated past it.
407
408   procedure Set_Name_Buffer;
409   --  Set the value stored in positions 1 .. Name_Len of the Name_Buffer
410
411   procedure Set_PSD_Pragma_Table;
412   --  Initializes contents of PSD_Pragma_Settings table from ALI table
413
414   procedure Set_String (S : String);
415   --  Sets characters of given string in Statement_Buffer, starting at the
416   --  Stm_Last + 1 position, and updating last past the string value.
417
418   procedure Set_String_Replace (S : String);
419   --  Replaces the last S'Length characters in the Statement_Buffer with the
420   --  characters of S. The caller must ensure that these characters do in fact
421   --  exist in the Statement_Buffer.
422
423   procedure Set_Unit_Name;
424   --  Given a unit name in the Name_Buffer, copy it into Statement_Buffer,
425   --  starting at the Stm_Last + 1 position and update Stm_Last past the
426   --  value. Each dot (.) will be qualified into double underscores (__).
427
428   procedure Set_Unit_Number (U : Unit_Id);
429   --  Sets unit number (first unit is 1, leading zeroes output to line up all
430   --  output unit numbers nicely as required by the value, and by the total
431   --  number of units.
432
433   procedure Write_Statement_Buffer;
434   --  Write out contents of statement buffer up to Stm_Last, and reset
435   --  Stm_Last to 0.
436
437   procedure Write_Statement_Buffer (S : String);
438   --  First writes its argument (using Set_String (S)), then writes out the
439   --  contents of statement buffer up to Stm_Last, and resets Stm_Last to 0.
440
441   procedure Write_Bind_Line (S : String);
442   --  Write S (an LF-terminated string) to the binder file (for use with
443   --  Set_Special_Output).
444
445   ------------------
446   -- Gen_Adafinal --
447   ------------------
448
449   procedure Gen_Adafinal is
450   begin
451      WBI ("   procedure " & Ada_Final_Name.all & " is");
452
453      --  Call s_stalib_adafinal to await termination of tasks and so on. We
454      --  want to do this if there is a main program, either in Ada or in some
455      --  other language. (Note that Bind_Main_Program is True for Ada mains,
456      --  but False for mains in other languages.) We do not want to do this if
457      --  we're binding a library.
458
459      if not Bind_For_Library and not CodePeer_Mode then
460         WBI ("      procedure s_stalib_adafinal;");
461         Set_String ("      pragma Import (C, s_stalib_adafinal, ");
462         Set_String ("""system__standard_library__adafinal"");");
463         Write_Statement_Buffer;
464      end if;
465
466      WBI ("");
467      WBI ("      procedure Runtime_Finalize;");
468      WBI ("      pragma Import (C, Runtime_Finalize, " &
469             """__gnat_runtime_finalize"");");
470      WBI ("");
471      WBI ("   begin");
472
473      if not CodePeer_Mode then
474         WBI ("      if not Is_Elaborated then");
475         WBI ("         return;");
476         WBI ("      end if;");
477         WBI ("      Is_Elaborated := False;");
478      end if;
479
480      WBI ("      Runtime_Finalize;");
481
482      --  By default (real targets), finalization is done differently depending
483      --  on whether this is the main program or a library.
484
485      if not CodePeer_Mode then
486         if not Bind_For_Library then
487            WBI ("      s_stalib_adafinal;");
488         elsif Lib_Final_Built then
489            WBI ("      finalize_library;");
490         else
491            WBI ("      null;");
492         end if;
493
494      --  Pragma Import C cannot be used on virtual targets, therefore call the
495      --  runtime finalization routine directly in CodePeer mode, where
496      --  imported functions are ignored.
497
498      else
499         WBI ("      System.Standard_Library.Adafinal;");
500      end if;
501
502      WBI ("   end " & Ada_Final_Name.all & ";");
503      WBI ("");
504   end Gen_Adafinal;
505
506   -----------------
507   -- Gen_Adainit --
508   -----------------
509
510   procedure Gen_Adainit (Elab_Order : Unit_Id_Array) is
511      Main_Priority : Int renames ALIs.Table (ALIs.First).Main_Priority;
512      Main_CPU      : Int renames ALIs.Table (ALIs.First).Main_CPU;
513
514   begin
515      --  Declare the access-to-subprogram type used for initialization of
516      --  of __gnat_finalize_library_objects. This is declared at library
517      --  level for compatibility with the type used in System.Soft_Links.
518      --  The import of the soft link which performs library-level object
519      --  finalization does not work for CodePeer, so regular Ada is used in
520      --  that case. For restricted run-time libraries (ZFP and Ravenscar)
521      --  tasks are non-terminating, so we do not want finalization.
522
523      if not Suppress_Standard_Library_On_Target
524        and then not CodePeer_Mode
525        and then not Configurable_Run_Time_On_Target
526      then
527         WBI ("   type No_Param_Proc is access procedure;");
528         WBI ("");
529      end if;
530
531      WBI ("   procedure " & Ada_Init_Name.all & " is");
532
533      --  In CodePeer mode, simplify adainit procedure by only calling
534      --  elaboration procedures.
535
536      if CodePeer_Mode then
537         WBI ("   begin");
538
539      --  If the standard library is suppressed, then the only global variables
540      --  that might be needed (by the Ravenscar profile) are the priority and
541      --  the processor for the environment task.
542
543      elsif Suppress_Standard_Library_On_Target then
544         if Main_Priority /= No_Main_Priority then
545            WBI ("      Main_Priority : Integer;");
546            WBI ("      pragma Import (C, Main_Priority," &
547                 " ""__gl_main_priority"");");
548            WBI ("");
549         end if;
550
551         if Main_CPU /= No_Main_CPU then
552            WBI ("      Main_CPU : Integer;");
553            WBI ("      pragma Import (C, Main_CPU," &
554                 " ""__gl_main_cpu"");");
555            WBI ("");
556         end if;
557
558         if System_Interrupts_Used
559           and then Partition_Elaboration_Policy_Specified = 'S'
560         then
561            WBI ("      procedure Install_Restricted_Handlers_Sequential;");
562            WBI ("      pragma Import (C," &
563                 "Install_Restricted_Handlers_Sequential," &
564                 " ""__gnat_attach_all_handlers"");");
565            WBI ("");
566         end if;
567
568         if System_Tasking_Restricted_Stages_Used
569           and then Partition_Elaboration_Policy_Specified = 'S'
570         then
571            WBI ("      Partition_Elaboration_Policy : Character;");
572            WBI ("      pragma Import (C, Partition_Elaboration_Policy," &
573                 " ""__gnat_partition_elaboration_policy"");");
574            WBI ("");
575            WBI ("      procedure Activate_All_Tasks_Sequential;");
576            WBI ("      pragma Import (C, Activate_All_Tasks_Sequential," &
577                 " ""__gnat_activate_all_tasks"");");
578            WBI ("");
579         end if;
580
581         if System_BB_CPU_Primitives_Multiprocessors_Used then
582            WBI ("      procedure Start_Slave_CPUs;");
583            WBI ("      pragma Import (C, Start_Slave_CPUs," &
584                 " ""__gnat_start_slave_cpus"");");
585            WBI ("");
586         end if;
587
588         --  A restricted run-time may attempt to initialize the main task's
589         --  secondary stack even if the stack is not used. Consequently,
590         --  the binder needs to initialize Binder_Sec_Stacks_Count anytime
591         --  System.Secondary_Stack is in the enclosure of the partition.
592
593         if System_Secondary_Stack_Used then
594            WBI ("      Binder_Sec_Stacks_Count : Natural;");
595            WBI ("      pragma Import (Ada, Binder_Sec_Stacks_Count, " &
596                 """__gnat_binder_ss_count"");");
597            WBI ("");
598         end if;
599
600         if Sec_Stack_Used then
601            WBI ("      Default_Secondary_Stack_Size : " &
602                 "System.Parameters.Size_Type;");
603            WBI ("      pragma Import (C, Default_Secondary_Stack_Size, " &
604                 """__gnat_default_ss_size"");");
605
606            WBI ("      Default_Sized_SS_Pool : System.Address;");
607            WBI ("      pragma Import (Ada, Default_Sized_SS_Pool, " &
608                 """__gnat_default_ss_pool"");");
609
610            WBI ("");
611         end if;
612
613         WBI ("   begin");
614
615         if Main_Priority /= No_Main_Priority then
616            Set_String ("      Main_Priority := ");
617            Set_Int    (Main_Priority);
618            Set_Char   (';');
619            Write_Statement_Buffer;
620         end if;
621
622         if Main_CPU /= No_Main_CPU then
623            Set_String ("      Main_CPU := ");
624            Set_Int    (Main_CPU);
625            Set_Char   (';');
626            Write_Statement_Buffer;
627         end if;
628
629         if System_Tasking_Restricted_Stages_Used
630           and then Partition_Elaboration_Policy_Specified = 'S'
631         then
632            Set_String ("      Partition_Elaboration_Policy := '");
633            Set_Char   (Partition_Elaboration_Policy_Specified);
634            Set_String ("';");
635            Write_Statement_Buffer;
636         end if;
637
638         if Main_Priority = No_Main_Priority
639           and then Main_CPU = No_Main_CPU
640           and then not System_Tasking_Restricted_Stages_Used
641         then
642            WBI ("      null;");
643         end if;
644
645         --  Generate default-sized secondary stack pool and set secondary
646         --  stack globals.
647
648         if Sec_Stack_Used then
649
650            --  Elaborate the body of the binder to initialize the default-
651            --  sized secondary stack pool.
652
653            WBI ("");
654            WBI ("      " & Get_Ada_Main_Name & "'Elab_Body;");
655
656            --  Generate the default-sized secondary stack pool and set the
657            --  related secondary stack globals.
658
659            Set_String ("      Default_Secondary_Stack_Size := ");
660
661            if Opt.Default_Sec_Stack_Size /= Opt.No_Stack_Size then
662               Set_Int (Opt.Default_Sec_Stack_Size);
663            else
664               Set_String ("System.Parameters.Runtime_Default_Sec_Stack_Size");
665            end if;
666
667            Set_Char (';');
668            Write_Statement_Buffer;
669
670            Set_String ("      Binder_Sec_Stacks_Count := ");
671            Set_Int (Num_Sec_Stacks);
672            Set_Char (';');
673            Write_Statement_Buffer;
674
675            WBI ("      Default_Sized_SS_Pool := " &
676                   "Sec_Default_Sized_Stacks'Address;");
677            WBI ("");
678
679         --  When a restricted run-time initializes the main task's secondary
680         --  stack but the program does not use it, no secondary stack is
681         --  generated. Binder_Sec_Stacks_Count is set to zero so the run-time
682         --  is aware that the lack of pre-allocated secondary stack is
683         --  expected.
684
685         elsif System_Secondary_Stack_Used then
686            WBI ("      Binder_Sec_Stacks_Count := 0;");
687         end if;
688
689      --  Normal case (standard library not suppressed). Set all global values
690      --  used by the run time.
691
692      else
693         WBI ("      Main_Priority : Integer;");
694         WBI ("      pragma Import (C, Main_Priority, " &
695              """__gl_main_priority"");");
696         WBI ("      Time_Slice_Value : Integer;");
697         WBI ("      pragma Import (C, Time_Slice_Value, " &
698              """__gl_time_slice_val"");");
699         WBI ("      WC_Encoding : Character;");
700         WBI ("      pragma Import (C, WC_Encoding, ""__gl_wc_encoding"");");
701         WBI ("      Locking_Policy : Character;");
702         WBI ("      pragma Import (C, Locking_Policy, " &
703              """__gl_locking_policy"");");
704         WBI ("      Queuing_Policy : Character;");
705         WBI ("      pragma Import (C, Queuing_Policy, " &
706              """__gl_queuing_policy"");");
707         WBI ("      Task_Dispatching_Policy : Character;");
708         WBI ("      pragma Import (C, Task_Dispatching_Policy, " &
709              """__gl_task_dispatching_policy"");");
710         WBI ("      Priority_Specific_Dispatching : System.Address;");
711         WBI ("      pragma Import (C, Priority_Specific_Dispatching, " &
712              """__gl_priority_specific_dispatching"");");
713         WBI ("      Num_Specific_Dispatching : Integer;");
714         WBI ("      pragma Import (C, Num_Specific_Dispatching, " &
715              """__gl_num_specific_dispatching"");");
716         WBI ("      Main_CPU : Integer;");
717         WBI ("      pragma Import (C, Main_CPU, " &
718              """__gl_main_cpu"");");
719
720         WBI ("      Interrupt_States : System.Address;");
721         WBI ("      pragma Import (C, Interrupt_States, " &
722              """__gl_interrupt_states"");");
723         WBI ("      Num_Interrupt_States : Integer;");
724         WBI ("      pragma Import (C, Num_Interrupt_States, " &
725              """__gl_num_interrupt_states"");");
726         WBI ("      Unreserve_All_Interrupts : Integer;");
727         WBI ("      pragma Import (C, Unreserve_All_Interrupts, " &
728              """__gl_unreserve_all_interrupts"");");
729
730         if Exception_Tracebacks or Exception_Tracebacks_Symbolic then
731            WBI ("      Exception_Tracebacks : Integer;");
732            WBI ("      pragma Import (C, Exception_Tracebacks, " &
733                 """__gl_exception_tracebacks"");");
734
735            if Exception_Tracebacks_Symbolic then
736               WBI ("      Exception_Tracebacks_Symbolic : Integer;");
737               WBI ("      pragma Import (C, Exception_Tracebacks_Symbolic, " &
738                    """__gl_exception_tracebacks_symbolic"");");
739            end if;
740         end if;
741
742         WBI ("      Detect_Blocking : Integer;");
743         WBI ("      pragma Import (C, Detect_Blocking, " &
744              """__gl_detect_blocking"");");
745         WBI ("      Default_Stack_Size : Integer;");
746         WBI ("      pragma Import (C, Default_Stack_Size, " &
747              """__gl_default_stack_size"");");
748
749         if Sec_Stack_Used then
750            WBI ("      Default_Secondary_Stack_Size : " &
751                 "System.Parameters.Size_Type;");
752            WBI ("      pragma Import (C, Default_Secondary_Stack_Size, " &
753                 """__gnat_default_ss_size"");");
754         end if;
755
756         WBI ("      Leap_Seconds_Support : Integer;");
757         WBI ("      pragma Import (C, Leap_Seconds_Support, " &
758              """__gl_leap_seconds_support"");");
759         WBI ("      Bind_Env_Addr : System.Address;");
760         WBI ("      pragma Import (C, Bind_Env_Addr, " &
761              """__gl_bind_env_addr"");");
762
763         --  Import entry point for elaboration time signal handler
764         --  installation, and indication of if it's been called previously.
765
766         WBI ("");
767         WBI ("      procedure Runtime_Initialize " &
768              "(Install_Handler : Integer);");
769         WBI ("      pragma Import (C, Runtime_Initialize, " &
770              """__gnat_runtime_initialize"");");
771
772         --  Import handlers attach procedure for sequential elaboration policy
773
774         if System_Interrupts_Used
775           and then Partition_Elaboration_Policy_Specified = 'S'
776         then
777            WBI ("      procedure Install_Restricted_Handlers_Sequential;");
778            WBI ("      pragma Import (C," &
779                 "Install_Restricted_Handlers_Sequential," &
780                 " ""__gnat_attach_all_handlers"");");
781            WBI ("");
782         end if;
783
784         --  Import task activation procedure for sequential elaboration
785         --  policy.
786
787         if System_Tasking_Restricted_Stages_Used
788           and then Partition_Elaboration_Policy_Specified = 'S'
789         then
790            WBI ("      Partition_Elaboration_Policy : Character;");
791            WBI ("      pragma Import (C, Partition_Elaboration_Policy," &
792                 " ""__gnat_partition_elaboration_policy"");");
793            WBI ("");
794            WBI ("      procedure Activate_All_Tasks_Sequential;");
795            WBI ("      pragma Import (C, Activate_All_Tasks_Sequential," &
796                 " ""__gnat_activate_all_tasks"");");
797         end if;
798
799         --  Import procedure to start slave cpus for bareboard runtime
800
801         if System_BB_CPU_Primitives_Multiprocessors_Used then
802            WBI ("      procedure Start_Slave_CPUs;");
803            WBI ("      pragma Import (C, Start_Slave_CPUs," &
804                 " ""__gnat_start_slave_cpus"");");
805         end if;
806
807         --  For restricted run-time libraries (ZFP and Ravenscar)
808         --  tasks are non-terminating, so we do not want finalization.
809
810         if not Configurable_Run_Time_On_Target then
811            WBI ("");
812            WBI ("      Finalize_Library_Objects : No_Param_Proc;");
813            WBI ("      pragma Import (C, Finalize_Library_Objects, " &
814                 """__gnat_finalize_library_objects"");");
815         end if;
816
817         --  Initialize stack limit variable of the environment task if the
818         --  stack check method is stack limit and stack check is enabled.
819
820         if Stack_Check_Limits_On_Target
821           and then (Stack_Check_Default_On_Target or Stack_Check_Switch_Set)
822         then
823            WBI ("");
824            WBI ("      procedure Initialize_Stack_Limit;");
825            WBI ("      pragma Import (C, Initialize_Stack_Limit, " &
826                 """__gnat_initialize_stack_limit"");");
827         end if;
828
829         --  When dispatching domains are used then we need to signal it
830         --  before calling the main procedure.
831
832         if Dispatching_Domains_Used then
833            WBI ("      procedure Freeze_Dispatching_Domains;");
834            WBI ("      pragma Import");
835            WBI ("        (Ada, Freeze_Dispatching_Domains, "
836                 & """__gnat_freeze_dispatching_domains"");");
837         end if;
838
839         --  Secondary stack global variables
840
841         WBI ("      Binder_Sec_Stacks_Count : Natural;");
842         WBI ("      pragma Import (Ada, Binder_Sec_Stacks_Count, " &
843              """__gnat_binder_ss_count"");");
844
845         WBI ("      Default_Sized_SS_Pool : System.Address;");
846         WBI ("      pragma Import (Ada, Default_Sized_SS_Pool, " &
847              """__gnat_default_ss_pool"");");
848
849         WBI ("");
850
851         --  Start of processing for Adainit
852
853         WBI ("   begin");
854         WBI ("      if Is_Elaborated then");
855         WBI ("         return;");
856         WBI ("      end if;");
857         WBI ("      Is_Elaborated := True;");
858
859         --  Call System.Elaboration_Allocators.Mark_Start_Of_Elaboration if
860         --  restriction No_Standard_Allocators_After_Elaboration is active.
861
862         if Cumulative_Restrictions.Set
863              (No_Standard_Allocators_After_Elaboration)
864         then
865            WBI ("      System.Elaboration_Allocators."
866                 & "Mark_Start_Of_Elaboration;");
867         end if;
868
869         --  Generate assignments to initialize globals
870
871         Set_String ("      Main_Priority := ");
872         Set_Int    (Main_Priority);
873         Set_Char   (';');
874         Write_Statement_Buffer;
875
876         Set_String ("      Time_Slice_Value := ");
877
878         if Task_Dispatching_Policy_Specified = 'F'
879           and then ALIs.Table (ALIs.First).Time_Slice_Value = -1
880         then
881            Set_Int (0);
882         else
883            Set_Int (ALIs.Table (ALIs.First).Time_Slice_Value);
884         end if;
885
886         Set_Char   (';');
887         Write_Statement_Buffer;
888
889         Set_String ("      WC_Encoding := '");
890         Set_Char   (Get_WC_Encoding);
891
892         Set_String ("';");
893         Write_Statement_Buffer;
894
895         Set_String ("      Locking_Policy := '");
896         Set_Char   (Locking_Policy_Specified);
897         Set_String ("';");
898         Write_Statement_Buffer;
899
900         Set_String ("      Queuing_Policy := '");
901         Set_Char   (Queuing_Policy_Specified);
902         Set_String ("';");
903         Write_Statement_Buffer;
904
905         Set_String ("      Task_Dispatching_Policy := '");
906         Set_Char   (Task_Dispatching_Policy_Specified);
907         Set_String ("';");
908         Write_Statement_Buffer;
909
910         if System_Tasking_Restricted_Stages_Used
911           and then Partition_Elaboration_Policy_Specified = 'S'
912         then
913            Set_String ("      Partition_Elaboration_Policy := '");
914            Set_Char   (Partition_Elaboration_Policy_Specified);
915            Set_String ("';");
916            Write_Statement_Buffer;
917         end if;
918
919         Gen_Restrictions;
920
921         WBI ("      Priority_Specific_Dispatching :=");
922         WBI ("        Local_Priority_Specific_Dispatching'Address;");
923
924         Set_String ("      Num_Specific_Dispatching := ");
925         Set_Int (PSD_Pragma_Settings.Last + 1);
926         Set_Char (';');
927         Write_Statement_Buffer;
928
929         Set_String ("      Main_CPU := ");
930         Set_Int    (Main_CPU);
931         Set_Char   (';');
932         Write_Statement_Buffer;
933
934         WBI ("      Interrupt_States := Local_Interrupt_States'Address;");
935
936         Set_String ("      Num_Interrupt_States := ");
937         Set_Int (IS_Pragma_Settings.Last + 1);
938         Set_Char (';');
939         Write_Statement_Buffer;
940
941         Set_String ("      Unreserve_All_Interrupts := ");
942
943         if Unreserve_All_Interrupts_Specified then
944            Set_String ("1");
945         else
946            Set_String ("0");
947         end if;
948
949         Set_Char (';');
950         Write_Statement_Buffer;
951
952         if Exception_Tracebacks or Exception_Tracebacks_Symbolic then
953            WBI ("      Exception_Tracebacks := 1;");
954
955            if Exception_Tracebacks_Symbolic then
956               WBI ("      Exception_Tracebacks_Symbolic := 1;");
957            end if;
958         end if;
959
960         Set_String ("      Detect_Blocking := ");
961
962         if Detect_Blocking then
963            Set_Int (1);
964         else
965            Set_Int (0);
966         end if;
967
968         Set_String (";");
969         Write_Statement_Buffer;
970
971         Set_String ("      Default_Stack_Size := ");
972         Set_Int (Default_Stack_Size);
973         Set_String (";");
974         Write_Statement_Buffer;
975
976         Set_String ("      Leap_Seconds_Support := ");
977
978         if Leap_Seconds_Support then
979            Set_Int (1);
980         else
981            Set_Int (0);
982         end if;
983
984         Set_String (";");
985         Write_Statement_Buffer;
986
987         if Bind_Env_String_Built then
988            WBI ("      Bind_Env_Addr := Bind_Env'Address;");
989         end if;
990
991         WBI ("");
992
993         --  Generate default-sized secondary stack pool and set secondary
994         --  stack globals.
995
996         if Sec_Stack_Used then
997
998            --  Elaborate the body of the binder to initialize the default-
999            --  sized secondary stack pool.
1000
1001            WBI ("      " & Get_Ada_Main_Name & "'Elab_Body;");
1002
1003            --  Generate the default-sized secondary stack pool and set the
1004            --  related secondary stack globals.
1005
1006            Set_String ("      Default_Secondary_Stack_Size := ");
1007
1008            if Opt.Default_Sec_Stack_Size /= Opt.No_Stack_Size then
1009               Set_Int (Opt.Default_Sec_Stack_Size);
1010            else
1011               Set_String ("System.Parameters.Runtime_Default_Sec_Stack_Size");
1012            end if;
1013
1014            Set_Char (';');
1015            Write_Statement_Buffer;
1016
1017            Set_String ("      Binder_Sec_Stacks_Count := ");
1018            Set_Int (Num_Sec_Stacks);
1019            Set_Char (';');
1020            Write_Statement_Buffer;
1021
1022            Set_String ("      Default_Sized_SS_Pool := ");
1023
1024            if Num_Sec_Stacks > 0 then
1025               Set_String ("Sec_Default_Sized_Stacks'Address;");
1026            else
1027               Set_String ("System.Null_Address;");
1028            end if;
1029
1030            Write_Statement_Buffer;
1031            WBI ("");
1032         end if;
1033
1034         --  Generate call to Runtime_Initialize
1035
1036         WBI ("      Runtime_Initialize (1);");
1037      end if;
1038
1039      --  Generate call to set Initialize_Scalar values if active
1040
1041      if Initialize_Scalars_Used then
1042         WBI ("");
1043         Set_String ("      System.Scalar_Values.Initialize ('");
1044         Set_Char (Initialize_Scalars_Mode1);
1045         Set_String ("', '");
1046         Set_Char (Initialize_Scalars_Mode2);
1047         Set_String ("');");
1048         Write_Statement_Buffer;
1049      end if;
1050
1051      --  Initialize stack limit variable of the environment task if the stack
1052      --  check method is stack limit and stack check is enabled.
1053
1054      if Stack_Check_Limits_On_Target
1055        and then (Stack_Check_Default_On_Target or Stack_Check_Switch_Set)
1056      then
1057         WBI ("");
1058         WBI ("      Initialize_Stack_Limit;");
1059      end if;
1060
1061      --  On CodePeer, the finalization of library objects is not relevant
1062
1063      if CodePeer_Mode then
1064         null;
1065
1066      --  If this is the main program case, attach finalize_library to the soft
1067      --  link. Do it only when not using a restricted run time, in which case
1068      --  tasks are non-terminating, so we do not want library-level
1069      --  finalization.
1070
1071      elsif not Bind_For_Library
1072        and then not Configurable_Run_Time_On_Target
1073        and then not Suppress_Standard_Library_On_Target
1074      then
1075         WBI ("");
1076
1077         if Lib_Final_Built then
1078            Set_String ("      Finalize_Library_Objects := ");
1079            Set_String ("finalize_library'access;");
1080         else
1081            Set_String ("      Finalize_Library_Objects := null;");
1082         end if;
1083
1084         Write_Statement_Buffer;
1085      end if;
1086
1087      --  Generate elaboration calls
1088
1089      if not CodePeer_Mode then
1090         WBI ("");
1091      end if;
1092
1093      Gen_Elab_Calls (Elab_Order);
1094
1095      if not CodePeer_Mode then
1096
1097         --  Call System.Elaboration_Allocators.Mark_Start_Of_Elaboration if
1098         --  restriction No_Standard_Allocators_After_Elaboration is active.
1099
1100         if Cumulative_Restrictions.Set
1101              (No_Standard_Allocators_After_Elaboration)
1102         then
1103            WBI
1104              ("      System.Elaboration_Allocators.Mark_End_Of_Elaboration;");
1105         end if;
1106
1107         --  From this point, no new dispatching domain can be created
1108
1109         if Dispatching_Domains_Used then
1110            WBI ("      Freeze_Dispatching_Domains;");
1111         end if;
1112
1113         --  Sequential partition elaboration policy
1114
1115         if Partition_Elaboration_Policy_Specified = 'S' then
1116            if System_Interrupts_Used then
1117               WBI ("      Install_Restricted_Handlers_Sequential;");
1118            end if;
1119
1120            if System_Tasking_Restricted_Stages_Used then
1121               WBI ("      Activate_All_Tasks_Sequential;");
1122            end if;
1123         end if;
1124
1125         if System_BB_CPU_Primitives_Multiprocessors_Used then
1126            WBI ("      Start_Slave_CPUs;");
1127         end if;
1128      end if;
1129
1130      WBI ("   end " & Ada_Init_Name.all & ";");
1131      WBI ("");
1132   end Gen_Adainit;
1133
1134   -------------------------
1135   -- Gen_Bind_Env_String --
1136   -------------------------
1137
1138   procedure Gen_Bind_Env_String is
1139      procedure Write_Name_With_Len (Nam : Name_Id);
1140      --  Write Nam as a string literal, prefixed with one
1141      --  character encoding Nam's length.
1142
1143      -------------------------
1144      -- Write_Name_With_Len --
1145      -------------------------
1146
1147      procedure Write_Name_With_Len (Nam : Name_Id) is
1148      begin
1149         Get_Name_String (Nam);
1150
1151         Start_String;
1152         Store_String_Char (Character'Val (Name_Len));
1153         Store_String_Chars (Name_Buffer (1 .. Name_Len));
1154
1155         Write_String_Table_Entry (End_String);
1156      end Write_Name_With_Len;
1157
1158      --  Local variables
1159
1160      Amp : Character;
1161      KN  : Name_Id := No_Name;
1162      VN  : Name_Id := No_Name;
1163
1164   --  Start of processing for Gen_Bind_Env_String
1165
1166   begin
1167      Bind_Environment.Get_First (KN, VN);
1168
1169      if VN = No_Name then
1170         return;
1171      end if;
1172
1173      Set_Special_Output (Write_Bind_Line'Access);
1174
1175      WBI ("   Bind_Env : aliased constant String :=");
1176      Amp := ' ';
1177      while VN /= No_Name loop
1178         Write_Str ("     " & Amp & ' ');
1179         Write_Name_With_Len (KN);
1180         Write_Str (" & ");
1181         Write_Name_With_Len (VN);
1182         Write_Eol;
1183
1184         Bind_Environment.Get_Next (KN, VN);
1185         Amp := '&';
1186      end loop;
1187      WBI ("     & ASCII.NUL;");
1188
1189      Cancel_Special_Output;
1190
1191      Bind_Env_String_Built := True;
1192   end Gen_Bind_Env_String;
1193
1194   --------------------------
1195   -- Gen_CodePeer_Wrapper --
1196   --------------------------
1197
1198   procedure Gen_CodePeer_Wrapper is
1199      Callee_Name : constant String := "Ada_Main_Program";
1200
1201   begin
1202      if ALIs.Table (ALIs.First).Main_Program = Proc then
1203         WBI ("   procedure " & CodePeer_Wrapper_Name & " is ");
1204         WBI ("   begin");
1205         WBI ("      " & Callee_Name & ";");
1206
1207      else
1208         WBI ("   function " & CodePeer_Wrapper_Name & " return Integer is");
1209         WBI ("   begin");
1210         WBI ("      return " & Callee_Name & ";");
1211      end if;
1212
1213      WBI ("   end " & CodePeer_Wrapper_Name & ";");
1214      WBI ("");
1215   end Gen_CodePeer_Wrapper;
1216
1217   --------------------
1218   -- Gen_Elab_Calls --
1219   --------------------
1220
1221   procedure Gen_Elab_Calls (Elab_Order : Unit_Id_Array) is
1222      Check_Elab_Flag : Boolean;
1223
1224   begin
1225      --  Loop through elaboration order entries
1226
1227      for E in Elab_Order'Range loop
1228         declare
1229            Unum : constant Unit_Id := Elab_Order (E);
1230            U    : Unit_Record renames Units.Table (Unum);
1231
1232            Unum_Spec : Unit_Id;
1233            --  This is the unit number of the spec that corresponds to
1234            --  this entry. It is the same as Unum except when the body
1235            --  and spec are different and we are currently processing
1236            --  the body, in which case it is the spec (Unum + 1).
1237
1238         begin
1239            if U.Utype = Is_Body then
1240               Unum_Spec := Unum + 1;
1241            else
1242               Unum_Spec := Unum;
1243            end if;
1244
1245            --  Nothing to do if predefined unit in no run time mode
1246
1247            if No_Run_Time_Mode and then Is_Predefined_File_Name (U.Sfile) then
1248               null;
1249
1250            --  Likewise if this is an interface to a stand alone library
1251
1252            elsif U.SAL_Interface then
1253               null;
1254
1255            --  Case of no elaboration code
1256
1257            elsif U.No_Elab
1258
1259              --  In CodePeer mode, we special case subprogram bodies which
1260              --  are handled in the 'else' part below, and lead to a call
1261              --  to <subp>'Elab_Subp_Body.
1262
1263              and then (not CodePeer_Mode
1264
1265                         --  Test for spec
1266
1267                         or else U.Utype = Is_Spec
1268                         or else U.Utype = Is_Spec_Only
1269                         or else U.Unit_Kind /= 's')
1270            then
1271               --  In the case of a body with a separate spec, where the
1272               --  separate spec has an elaboration entity defined, this is
1273               --  where we increment the elaboration entity if one exists.
1274
1275               --  Likewise for lone specs with an elaboration entity defined
1276               --  despite No_Elaboration_Code, e.g. when requested to preserve
1277               --  control flow.
1278
1279               if (U.Utype = Is_Body or else U.Utype = Is_Spec_Only)
1280                 and then Units.Table (Unum_Spec).Set_Elab_Entity
1281                 and then not CodePeer_Mode
1282               then
1283                  Set_String ("      E");
1284                  Set_Unit_Number (Unum_Spec);
1285                  Set_String (" := E");
1286                  Set_Unit_Number (Unum_Spec);
1287                  Set_String (" + 1;");
1288                  Write_Statement_Buffer;
1289               end if;
1290
1291            --  Here if elaboration code is present. If binding a library
1292            --  or if there is a non-Ada main subprogram then we generate:
1293
1294            --    if uname_E = 0 then
1295            --       uname'elab_[spec|body];
1296            --    end if;
1297            --    uname_E := uname_E + 1;
1298
1299            --  Otherwise, elaboration routines are called unconditionally:
1300
1301            --    uname'elab_[spec|body];
1302            --    uname_E := uname_E + 1;
1303
1304            --  The uname_E increment is skipped if this is a separate spec,
1305            --  since it will be done when we process the body.
1306
1307            --  In CodePeer mode, we do not generate any reference to xxx_E
1308            --  variables, only calls to 'Elab* subprograms.
1309
1310            else
1311               --  Check incompatibilities with No_Multiple_Elaboration
1312
1313               if not CodePeer_Mode
1314                 and then Cumulative_Restrictions.Set (No_Multiple_Elaboration)
1315               then
1316                  --  Force_Checking_Of_Elaboration_Flags (-F) not allowed
1317
1318                  if Force_Checking_Of_Elaboration_Flags then
1319                     Osint.Fail
1320                       ("-F (force elaboration checks) switch not allowed "
1321                        & "with restriction No_Multiple_Elaboration active");
1322
1323                  --  Interfacing of libraries not allowed
1324
1325                  elsif Interface_Library_Unit then
1326                     Osint.Fail
1327                       ("binding of interfaced libraries not allowed "
1328                        & "with restriction No_Multiple_Elaboration active");
1329
1330                  --  Non-Ada main program not allowed
1331
1332                  elsif not Bind_Main_Program then
1333                     Osint.Fail
1334                       ("non-Ada main program not allowed "
1335                        & "with restriction No_Multiple_Elaboration active");
1336                  end if;
1337               end if;
1338
1339               --  OK, see if we need to test elaboration flag
1340
1341               Check_Elab_Flag :=
1342                 Units.Table (Unum_Spec).Set_Elab_Entity
1343                   and then not CodePeer_Mode
1344                   and then (Force_Checking_Of_Elaboration_Flags
1345                              or Interface_Library_Unit
1346                              or not Bind_Main_Program);
1347
1348               if Check_Elab_Flag then
1349                  Set_String ("      if E");
1350                  Set_Unit_Number (Unum_Spec);
1351                  Set_String (" = 0 then");
1352                  Write_Statement_Buffer;
1353                  Set_String ("   ");
1354               end if;
1355
1356               Set_String ("      ");
1357               Get_Decoded_Name_String_With_Brackets (U.Uname);
1358
1359               if Name_Buffer (Name_Len) = 's' then
1360                  Name_Buffer (Name_Len - 1 .. Name_Len + 8) :=
1361                    "'elab_spec";
1362                  Name_Len := Name_Len + 8;
1363
1364               --  Special case in CodePeer mode for subprogram bodies
1365               --  which correspond to CodePeer 'Elab_Subp_Body special
1366               --  init procedure.
1367
1368               elsif U.Unit_Kind = 's' and CodePeer_Mode then
1369                  Name_Buffer (Name_Len - 1 .. Name_Len + 13) :=
1370                    "'elab_subp_body";
1371                  Name_Len := Name_Len + 13;
1372
1373               else
1374                  Name_Buffer (Name_Len - 1 .. Name_Len + 8) :=
1375                    "'elab_body";
1376                  Name_Len := Name_Len + 8;
1377               end if;
1378
1379               Set_Casing (U.Icasing);
1380               Set_Name_Buffer;
1381               Set_Char (';');
1382               Write_Statement_Buffer;
1383
1384               if Check_Elab_Flag then
1385                  WBI ("      end if;");
1386               end if;
1387
1388               if U.Utype /= Is_Spec
1389                 and then not CodePeer_Mode
1390                 and then Units.Table (Unum_Spec).Set_Elab_Entity
1391               then
1392                  Set_String ("      E");
1393                  Set_Unit_Number (Unum_Spec);
1394                  Set_String (" := E");
1395                  Set_Unit_Number (Unum_Spec);
1396                  Set_String (" + 1;");
1397                  Write_Statement_Buffer;
1398               end if;
1399            end if;
1400         end;
1401      end loop;
1402   end Gen_Elab_Calls;
1403
1404   ------------------------
1405   -- Gen_Elab_Externals --
1406   ------------------------
1407
1408   procedure Gen_Elab_Externals (Elab_Order : Unit_Id_Array) is
1409   begin
1410      if CodePeer_Mode then
1411         return;
1412      end if;
1413
1414      for E in Elab_Order'Range loop
1415         declare
1416            Unum : constant Unit_Id := Elab_Order (E);
1417            U    : Unit_Record renames Units.Table (Unum);
1418
1419         begin
1420            --  Check for Elab_Entity to be set for this unit
1421
1422            if U.Set_Elab_Entity
1423
1424              --  Don't generate reference for stand alone library
1425
1426              and then not U.SAL_Interface
1427
1428              --  Don't generate reference for predefined file in No_Run_Time
1429              --  mode, since we don't include the object files in this case
1430
1431              and then not
1432                (No_Run_Time_Mode
1433                  and then Is_Predefined_File_Name (U.Sfile))
1434            then
1435               Get_Name_String (U.Sfile);
1436               Set_String ("   ");
1437               Set_String ("E");
1438               Set_Unit_Number (Unum);
1439               Set_String (" : Short_Integer; pragma Import (Ada, E");
1440               Set_Unit_Number (Unum);
1441               Set_String (", """);
1442               Get_Name_String (U.Uname);
1443               Set_Unit_Name;
1444               Set_String ("_E"");");
1445               Write_Statement_Buffer;
1446            end if;
1447         end;
1448      end loop;
1449
1450      WBI ("");
1451   end Gen_Elab_Externals;
1452
1453   --------------------
1454   -- Gen_Elab_Order --
1455   --------------------
1456
1457   procedure Gen_Elab_Order (Elab_Order : Unit_Id_Array) is
1458   begin
1459      WBI ("");
1460      WBI ("   --  BEGIN ELABORATION ORDER");
1461
1462      for J in Elab_Order'Range loop
1463         Set_String ("   --  ");
1464         Get_Name_String (Units.Table (Elab_Order (J)).Uname);
1465         Set_Name_Buffer;
1466         Write_Statement_Buffer;
1467      end loop;
1468
1469      WBI ("   --  END ELABORATION ORDER");
1470   end Gen_Elab_Order;
1471
1472   --------------------------
1473   -- Gen_Finalize_Library --
1474   --------------------------
1475
1476   procedure Gen_Finalize_Library (Elab_Order : Unit_Id_Array) is
1477      procedure Gen_Header;
1478      --  Generate the header of the finalization routine
1479
1480      ----------------
1481      -- Gen_Header --
1482      ----------------
1483
1484      procedure Gen_Header is
1485      begin
1486         WBI ("   procedure finalize_library is");
1487         WBI ("   begin");
1488      end Gen_Header;
1489
1490      --  Local variables
1491
1492      Count : Int := 1;
1493      U     : Unit_Record;
1494      Uspec : Unit_Record;
1495      Unum  : Unit_Id;
1496
1497   --  Start of processing for Gen_Finalize_Library
1498
1499   begin
1500      if CodePeer_Mode then
1501         return;
1502      end if;
1503
1504      for E in reverse Elab_Order'Range loop
1505         Unum := Elab_Order (E);
1506         U    := Units.Table (Unum);
1507
1508         --  Dealing with package bodies is a little complicated. In such
1509         --  cases we must retrieve the package spec since it contains the
1510         --  spec of the body finalizer.
1511
1512         if U.Utype = Is_Body then
1513            Unum  := Unum + 1;
1514            Uspec := Units.Table (Unum);
1515         else
1516            Uspec := U;
1517         end if;
1518
1519         Get_Name_String (Uspec.Uname);
1520
1521         --  We are only interested in non-generic packages
1522
1523         if U.Unit_Kind /= 'p' or else U.Is_Generic then
1524            null;
1525
1526         --  That aren't an interface to a stand alone library
1527
1528         elsif U.SAL_Interface then
1529            null;
1530
1531         --  Case of no finalization
1532
1533         elsif not U.Has_Finalizer then
1534
1535            --  The only case in which we have to do something is if this
1536            --  is a body, with a separate spec, where the separate spec
1537            --  has a finalizer. In that case, this is where we decrement
1538            --  the elaboration entity.
1539
1540            if U.Utype = Is_Body and then Uspec.Has_Finalizer then
1541               if not Lib_Final_Built then
1542                  Gen_Header;
1543                  Lib_Final_Built := True;
1544               end if;
1545
1546               Set_String ("      E");
1547               Set_Unit_Number (Unum);
1548               Set_String (" := E");
1549               Set_Unit_Number (Unum);
1550               Set_String (" - 1;");
1551               Write_Statement_Buffer;
1552            end if;
1553
1554         else
1555            if not Lib_Final_Built then
1556               Gen_Header;
1557               Lib_Final_Built := True;
1558            end if;
1559
1560            --  Generate:
1561            --    declare
1562            --       procedure F<Count>;
1563
1564            Set_String ("      declare");
1565            Write_Statement_Buffer;
1566
1567            Set_String ("         procedure F");
1568            Set_Int    (Count);
1569            Set_Char   (';');
1570            Write_Statement_Buffer;
1571
1572            --  Generate:
1573            --    pragma Import (Ada, F<Count>,
1574            --                  "xx__yy__finalize_[body|spec]");
1575
1576            Set_String ("         pragma Import (Ada, F");
1577            Set_Int (Count);
1578            Set_String (", """);
1579
1580            --  Perform name construction
1581
1582            Set_Unit_Name;
1583            Set_String ("__finalize_");
1584
1585            --  Package spec processing
1586
1587            if U.Utype = Is_Spec
1588              or else U.Utype = Is_Spec_Only
1589            then
1590               Set_String ("spec");
1591
1592            --  Package body processing
1593
1594            else
1595               Set_String ("body");
1596            end if;
1597
1598            Set_String (""");");
1599            Write_Statement_Buffer;
1600
1601            --  If binding a library or if there is a non-Ada main subprogram
1602            --  then we generate:
1603
1604            --    begin
1605            --       uname_E := uname_E - 1;
1606            --       if uname_E = 0 then
1607            --          F<Count>;
1608            --       end if;
1609            --    end;
1610
1611            --  Otherwise, finalization routines are called unconditionally:
1612
1613            --    begin
1614            --       uname_E := uname_E - 1;
1615            --       F<Count>;
1616            --    end;
1617
1618            --  The uname_E decrement is skipped if this is a separate spec,
1619            --  since it will be done when we process the body.
1620
1621            WBI ("      begin");
1622
1623            if U.Utype /= Is_Spec then
1624               Set_String ("         E");
1625               Set_Unit_Number (Unum);
1626               Set_String (" := E");
1627               Set_Unit_Number (Unum);
1628               Set_String (" - 1;");
1629               Write_Statement_Buffer;
1630            end if;
1631
1632            if Interface_Library_Unit or not Bind_Main_Program then
1633               Set_String ("         if E");
1634               Set_Unit_Number (Unum);
1635               Set_String (" = 0 then");
1636               Write_Statement_Buffer;
1637               Set_String ("   ");
1638            end if;
1639
1640            Set_String ("         F");
1641            Set_Int    (Count);
1642            Set_Char   (';');
1643            Write_Statement_Buffer;
1644
1645            if Interface_Library_Unit or not Bind_Main_Program then
1646               WBI ("         end if;");
1647            end if;
1648
1649            WBI ("      end;");
1650
1651            Count := Count + 1;
1652         end if;
1653      end loop;
1654
1655      if Lib_Final_Built then
1656
1657         --  It is possible that the finalization of a library-level object
1658         --  raised an exception. In that case import the actual exception
1659         --  and the routine necessary to raise it.
1660
1661         WBI ("      declare");
1662         WBI ("         procedure Reraise_Library_Exception_If_Any;");
1663
1664         Set_String ("            pragma Import (Ada, ");
1665         Set_String ("Reraise_Library_Exception_If_Any, ");
1666         Set_String ("""__gnat_reraise_library_exception_if_any"");");
1667         Write_Statement_Buffer;
1668
1669         WBI ("      begin");
1670         WBI ("         Reraise_Library_Exception_If_Any;");
1671         WBI ("      end;");
1672         WBI ("   end finalize_library;");
1673         WBI ("");
1674      end if;
1675   end Gen_Finalize_Library;
1676
1677   --------------
1678   -- Gen_Main --
1679   --------------
1680
1681   procedure Gen_Main is
1682   begin
1683      if not No_Main_Subprogram then
1684
1685         --  To call the main program, we declare it using a pragma Import
1686         --  Ada with the right link name.
1687
1688         --  It might seem more obvious to "with" the main program, and call
1689         --  it in the normal Ada manner. We do not do this for three
1690         --  reasons:
1691
1692         --    1. It is more efficient not to recompile the main program
1693         --    2. We are not entitled to assume the source is accessible
1694         --    3. We don't know what options to use to compile it
1695
1696         --  It is really reason 3 that is most critical (indeed we used
1697         --  to generate the "with", but several regression tests failed).
1698
1699         if ALIs.Table (ALIs.First).Main_Program = Func then
1700            WBI ("   function Ada_Main_Program return Integer;");
1701         else
1702            WBI ("   procedure Ada_Main_Program;");
1703         end if;
1704
1705         Set_String ("   pragma Import (Ada, Ada_Main_Program, """);
1706         Get_Name_String (Units.Table (First_Unit_Entry).Uname);
1707         Set_Main_Program_Name;
1708         Set_String (""");");
1709
1710         Write_Statement_Buffer;
1711         WBI ("");
1712
1713         --  For CodePeer, declare a wrapper for the user-defined main program
1714
1715         if CodePeer_Mode then
1716            Gen_CodePeer_Wrapper;
1717         end if;
1718      end if;
1719
1720      if Exit_Status_Supported_On_Target then
1721         Set_String ("   function ");
1722      else
1723         Set_String ("   procedure ");
1724      end if;
1725
1726      Set_String (Get_Main_Name);
1727
1728      if Command_Line_Args_On_Target then
1729         Write_Statement_Buffer;
1730         WBI ("     (argc : Integer;");
1731         WBI ("      argv : System.Address;");
1732         WBI ("      envp : System.Address)");
1733
1734         if Exit_Status_Supported_On_Target then
1735            WBI ("      return Integer");
1736         end if;
1737
1738         WBI ("   is");
1739
1740      else
1741         if Exit_Status_Supported_On_Target then
1742            Set_String (" return Integer is");
1743         else
1744            Set_String (" is");
1745         end if;
1746
1747         Write_Statement_Buffer;
1748      end if;
1749
1750      if Opt.Default_Exit_Status /= 0
1751        and then Bind_Main_Program
1752        and then not Configurable_Run_Time_Mode
1753      then
1754         WBI ("      procedure Set_Exit_Status (Status : Integer);");
1755         WBI ("      pragma Import (C, Set_Exit_Status, " &
1756                     """__gnat_set_exit_status"");");
1757         WBI ("");
1758      end if;
1759
1760      --  Initialize and Finalize
1761
1762      if not CodePeer_Mode
1763        and then not Cumulative_Restrictions.Set (No_Finalization)
1764      then
1765         WBI ("      procedure Initialize (Addr : System.Address);");
1766         WBI ("      pragma Import (C, Initialize, ""__gnat_initialize"");");
1767         WBI ("");
1768         WBI ("      procedure Finalize;");
1769         WBI ("      pragma Import (C, Finalize, ""__gnat_finalize"");");
1770      end if;
1771
1772      --  If we want to analyze the stack, we must import corresponding symbols
1773
1774      if Dynamic_Stack_Measurement then
1775         WBI ("");
1776         WBI ("      procedure Output_Results;");
1777         WBI ("      pragma Import (C, Output_Results, " &
1778              """__gnat_stack_usage_output_results"");");
1779
1780         WBI ("");
1781         WBI ("      " &
1782              "procedure Initialize_Stack_Analysis (Buffer_Size : Natural);");
1783         WBI ("      pragma Import (C, Initialize_Stack_Analysis, " &
1784              """__gnat_stack_usage_initialize"");");
1785      end if;
1786
1787      --  Deal with declarations for main program case
1788
1789      if not No_Main_Subprogram then
1790         if ALIs.Table (ALIs.First).Main_Program = Func then
1791            WBI ("      Result : Integer;");
1792            WBI ("");
1793         end if;
1794
1795         if Bind_Main_Program
1796           and not Suppress_Standard_Library_On_Target
1797           and not CodePeer_Mode
1798         then
1799            WBI ("      SEH : aliased array (1 .. 2) of Integer;");
1800            WBI ("");
1801         end if;
1802      end if;
1803
1804      --  Generate a reference to Ada_Main_Program_Name. This symbol is not
1805      --  referenced elsewhere in the generated program, but is needed by
1806      --  the debugger (that's why it is generated in the first place). The
1807      --  reference stops Ada_Main_Program_Name from being optimized away by
1808      --  smart linkers, such as the AiX linker.
1809
1810      --  Because this variable is unused, we make this variable "aliased"
1811      --  with a pragma Volatile in order to tell the compiler to preserve
1812      --  this variable at any level of optimization.
1813
1814      if Bind_Main_Program and not CodePeer_Mode then
1815         WBI ("      Ensure_Reference : aliased System.Address := " &
1816              "Ada_Main_Program_Name'Address;");
1817         WBI ("      pragma Volatile (Ensure_Reference);");
1818         WBI ("");
1819      end if;
1820
1821      WBI ("   begin");
1822
1823      --  Acquire command line arguments if present on target
1824
1825      if CodePeer_Mode then
1826         null;
1827
1828      elsif Command_Line_Args_On_Target then
1829         WBI ("      gnat_argc := argc;");
1830         WBI ("      gnat_argv := argv;");
1831         WBI ("      gnat_envp := envp;");
1832         WBI ("");
1833
1834      --  If configurable run time and no command line args, then nothing needs
1835      --  to be done since the gnat_argc/argv/envp variables are suppressed in
1836      --  this case.
1837
1838      elsif Configurable_Run_Time_On_Target then
1839         null;
1840
1841      --  Otherwise set dummy values (to be filled in by some other unit?)
1842
1843      else
1844         WBI ("      gnat_argc := 0;");
1845         WBI ("      gnat_argv := System.Null_Address;");
1846         WBI ("      gnat_envp := System.Null_Address;");
1847      end if;
1848
1849      if Opt.Default_Exit_Status /= 0
1850        and then Bind_Main_Program
1851        and then not Configurable_Run_Time_Mode
1852      then
1853         Set_String ("      Set_Exit_Status (");
1854         Set_Int (Opt.Default_Exit_Status);
1855         Set_String (");");
1856         Write_Statement_Buffer;
1857      end if;
1858
1859      if Dynamic_Stack_Measurement then
1860         Set_String ("      Initialize_Stack_Analysis (");
1861         Set_Int (Dynamic_Stack_Measurement_Array_Size);
1862         Set_String (");");
1863         Write_Statement_Buffer;
1864      end if;
1865
1866      if not Cumulative_Restrictions.Set (No_Finalization)
1867        and then not CodePeer_Mode
1868      then
1869         if not No_Main_Subprogram
1870           and then Bind_Main_Program
1871           and then not Suppress_Standard_Library_On_Target
1872         then
1873            WBI ("      Initialize (SEH'Address);");
1874         else
1875            WBI ("      Initialize (System.Null_Address);");
1876         end if;
1877      end if;
1878
1879      WBI ("      " & Ada_Init_Name.all & ";");
1880
1881      if not No_Main_Subprogram then
1882         if CodePeer_Mode then
1883            if ALIs.Table (ALIs.First).Main_Program = Proc then
1884               WBI ("      " & CodePeer_Wrapper_Name & ";");
1885            else
1886               WBI ("      Result := " & CodePeer_Wrapper_Name & ";");
1887            end if;
1888
1889         elsif ALIs.Table (ALIs.First).Main_Program = Proc then
1890            WBI ("      Ada_Main_Program;");
1891
1892         else
1893            WBI ("      Result := Ada_Main_Program;");
1894         end if;
1895      end if;
1896
1897      --  Adafinal call is skipped if no finalization
1898
1899      if not Cumulative_Restrictions.Set (No_Finalization) then
1900         WBI ("      adafinal;");
1901      end if;
1902
1903      --  Prints the result of static stack analysis
1904
1905      if Dynamic_Stack_Measurement then
1906         WBI ("      Output_Results;");
1907      end if;
1908
1909      --  Finalize is only called if we have a run time
1910
1911      if not Cumulative_Restrictions.Set (No_Finalization)
1912        and then not CodePeer_Mode
1913      then
1914         WBI ("      Finalize;");
1915      end if;
1916
1917      --  Return result
1918
1919      if Exit_Status_Supported_On_Target then
1920         if No_Main_Subprogram
1921           or else ALIs.Table (ALIs.First).Main_Program = Proc
1922         then
1923            WBI ("      return (gnat_exit_status);");
1924         else
1925            WBI ("      return (Result);");
1926         end if;
1927      end if;
1928
1929      WBI ("   end;");
1930      WBI ("");
1931   end Gen_Main;
1932
1933   ------------------------------
1934   -- Gen_Object_Files_Options --
1935   ------------------------------
1936
1937   procedure Gen_Object_Files_Options (Elab_Order : Unit_Id_Array) is
1938      Lgnat : Natural;
1939      --  This keeps track of the position in the sorted set of entries in the
1940      --  Linker_Options table of where the first entry from an internal file
1941      --  appears.
1942
1943      Linker_Option_List_Started : Boolean := False;
1944      --  Set to True when "LINKER OPTION LIST" is displayed
1945
1946      procedure Write_Linker_Option;
1947      --  Write binder info linker option
1948
1949      -------------------------
1950      -- Write_Linker_Option --
1951      -------------------------
1952
1953      procedure Write_Linker_Option is
1954         Start : Natural;
1955         Stop  : Natural;
1956
1957      begin
1958         --  Loop through string, breaking at null's
1959
1960         Start := 1;
1961         while Start < Name_Len loop
1962
1963            --  Find null ending this section
1964
1965            Stop := Start + 1;
1966            while Name_Buffer (Stop) /= ASCII.NUL
1967              and then Stop <= Name_Len loop
1968               Stop := Stop + 1;
1969            end loop;
1970
1971            --  Process section if non-null
1972
1973            if Stop > Start then
1974               if Output_Linker_Option_List then
1975                  if not Zero_Formatting then
1976                     if not Linker_Option_List_Started then
1977                        Linker_Option_List_Started := True;
1978                        Write_Eol;
1979                        Write_Str ("     LINKER OPTION LIST");
1980                        Write_Eol;
1981                        Write_Eol;
1982                     end if;
1983
1984                     Write_Str ("   ");
1985                  end if;
1986
1987                  Write_Str (Name_Buffer (Start .. Stop - 1));
1988                  Write_Eol;
1989               end if;
1990               WBI ("   --   " & Name_Buffer (Start .. Stop - 1));
1991            end if;
1992
1993            Start := Stop + 1;
1994         end loop;
1995      end Write_Linker_Option;
1996
1997   --  Start of processing for Gen_Object_Files_Options
1998
1999   begin
2000      WBI ("--  BEGIN Object file/option list");
2001
2002      if Object_List_Filename /= null then
2003         Set_List_File (Object_List_Filename.all);
2004      end if;
2005
2006      for E in Elab_Order'Range loop
2007
2008         --  If not spec that has an associated body, then generate a comment
2009         --  giving the name of the corresponding object file.
2010
2011         if not Units.Table (Elab_Order (E)).SAL_Interface
2012           and then Units.Table (Elab_Order (E)).Utype /= Is_Spec
2013         then
2014            Get_Name_String
2015              (ALIs.Table
2016                (Units.Table (Elab_Order (E)).My_ALI).Ofile_Full_Name);
2017
2018            --  If the presence of an object file is necessary or if it exists,
2019            --  then use it.
2020
2021            if not Hostparm.Exclude_Missing_Objects
2022              or else
2023                System.OS_Lib.Is_Regular_File (Name_Buffer (1 .. Name_Len))
2024            then
2025               WBI ("   --   " & Name_Buffer (1 .. Name_Len));
2026
2027               if Output_Object_List then
2028                  Write_Str (Name_Buffer (1 .. Name_Len));
2029                  Write_Eol;
2030               end if;
2031            end if;
2032         end if;
2033      end loop;
2034
2035      if Object_List_Filename /= null then
2036         Close_List_File;
2037      end if;
2038
2039      --  Add a "-Ldir" for each directory in the object path
2040
2041      for J in 1 .. Nb_Dir_In_Obj_Search_Path loop
2042         declare
2043            Dir : constant String_Ptr := Dir_In_Obj_Search_Path (J);
2044
2045         begin
2046            Name_Len := 0;
2047            Add_Str_To_Name_Buffer ("-L");
2048            Add_Str_To_Name_Buffer (Dir.all);
2049            Write_Linker_Option;
2050         end;
2051      end loop;
2052
2053      if not (Opt.No_Run_Time_Mode or Opt.No_Stdlib) then
2054         Name_Len := 0;
2055
2056         if Opt.Shared_Libgnat then
2057            Add_Str_To_Name_Buffer ("-shared");
2058         else
2059            Add_Str_To_Name_Buffer ("-static");
2060         end if;
2061
2062         --  Write directly to avoid inclusion in -K output as -static and
2063         --  -shared are not usually specified linker options.
2064
2065         WBI ("   --   " & Name_Buffer (1 .. Name_Len));
2066      end if;
2067
2068      --  Sort linker options
2069
2070      --  This sort accomplishes two important purposes:
2071
2072      --    a) All application files are sorted to the front, and all GNAT
2073      --       internal files are sorted to the end. This results in a well
2074      --       defined dividing line between the two sets of files, for the
2075      --       purpose of inserting certain standard library references into
2076      --       the linker arguments list.
2077
2078      --    b) Given two different units, we sort the linker options so that
2079      --       those from a unit earlier in the elaboration order comes later
2080      --       in the list. This is a heuristic designed to create a more
2081      --       friendly order of linker options when the operations appear in
2082      --       separate units. The idea is that if unit A must be elaborated
2083      --       before unit B, then it is more likely that B references
2084      --       libraries included by A, than vice versa, so we want libraries
2085      --       included by A to come after libraries included by B.
2086
2087      --  These two criteria are implemented by function Lt_Linker_Option. Note
2088      --  that a special case of b) is that specs are elaborated before bodies,
2089      --  so linker options from specs come after linker options for bodies,
2090      --  and again, the assumption is that libraries used by the body are more
2091      --  likely to reference libraries used by the spec, than vice versa.
2092
2093      Sort
2094        (Linker_Options.Last,
2095         Move_Linker_Option'Access,
2096         Lt_Linker_Option'Access);
2097
2098      --  Write user linker options, i.e. the set of linker options that come
2099      --  from all files other than GNAT internal files, Lgnat is left set to
2100      --  point to the first entry from a GNAT internal file, or past the end
2101      --  of the entries if there are no internal files.
2102
2103      Lgnat := Linker_Options.Last + 1;
2104
2105      for J in 1 .. Linker_Options.Last loop
2106         if not Linker_Options.Table (J).Internal_File then
2107            Get_Name_String (Linker_Options.Table (J).Name);
2108            Write_Linker_Option;
2109         else
2110            Lgnat := J;
2111            exit;
2112         end if;
2113      end loop;
2114
2115      --  Now we insert standard linker options that must appear after the
2116      --  entries from user files, and before the entries from GNAT run-time
2117      --  files. The reason for this decision is that libraries referenced
2118      --  by internal routines may reference these standard library entries.
2119
2120      --  Note that we do not insert anything when pragma No_Run_Time has
2121      --  been specified or when the standard libraries are not to be used,
2122      --  otherwise on some platforms, we may get duplicate symbols when
2123      --  linking (not clear if this is still the case, but it is harmless).
2124
2125      if not (Opt.No_Run_Time_Mode or else Opt.No_Stdlib) then
2126         if With_GNARL then
2127            Name_Len := 0;
2128
2129            if Opt.Shared_Libgnat then
2130               Add_Str_To_Name_Buffer (Shared_Lib ("gnarl"));
2131            else
2132               Add_Str_To_Name_Buffer ("-lgnarl");
2133            end if;
2134
2135            Write_Linker_Option;
2136         end if;
2137
2138         Name_Len := 0;
2139
2140         if Opt.Shared_Libgnat then
2141            Add_Str_To_Name_Buffer (Shared_Lib ("gnat"));
2142         else
2143            Add_Str_To_Name_Buffer ("-lgnat");
2144         end if;
2145
2146         Write_Linker_Option;
2147      end if;
2148
2149      --  Write linker options from all internal files
2150
2151      for J in Lgnat .. Linker_Options.Last loop
2152         Get_Name_String (Linker_Options.Table (J).Name);
2153         Write_Linker_Option;
2154      end loop;
2155
2156      if Output_Linker_Option_List and then not Zero_Formatting then
2157         Write_Eol;
2158      end if;
2159
2160      WBI ("--  END Object file/option list   ");
2161   end Gen_Object_Files_Options;
2162
2163   ---------------------
2164   -- Gen_Output_File --
2165   ---------------------
2166
2167   procedure Gen_Output_File
2168     (Filename   : String;
2169      Elab_Order : Unit_Id_Array)
2170   is
2171   begin
2172      --  Acquire settings for Interrupt_State pragmas
2173
2174      Set_IS_Pragma_Table;
2175
2176      --  Acquire settings for Priority_Specific_Dispatching pragma
2177
2178      Set_PSD_Pragma_Table;
2179
2180      --  Override time slice value if -T switch is set
2181
2182      if Time_Slice_Set then
2183         ALIs.Table (ALIs.First).Time_Slice_Value := Opt.Time_Slice_Value;
2184      end if;
2185
2186      --  Count number of elaboration calls
2187
2188      for E in Elab_Order'Range loop
2189         if Units.Table (Elab_Order (E)).No_Elab then
2190            null;
2191         else
2192            Num_Elab_Calls := Num_Elab_Calls + 1;
2193         end if;
2194      end loop;
2195
2196      --  Count the number of statically allocated stacks to be generated by
2197      --  the binder. If the user has specified the number of default-sized
2198      --  secondary stacks, use that number. Otherwise start the count at one
2199      --  as the binder is responsible for creating a secondary stack for the
2200      --  main task.
2201
2202      if Opt.Quantity_Of_Default_Size_Sec_Stacks /= -1 then
2203         Num_Sec_Stacks := Quantity_Of_Default_Size_Sec_Stacks;
2204      elsif Sec_Stack_Used then
2205         Num_Sec_Stacks := 1;
2206      end if;
2207
2208      for J in Units.First .. Units.Last loop
2209         Num_Primary_Stacks :=
2210           Num_Primary_Stacks + Units.Table (J).Primary_Stack_Count;
2211
2212         Num_Sec_Stacks :=
2213           Num_Sec_Stacks + Units.Table (J).Sec_Stack_Count;
2214      end loop;
2215
2216      --  Generate output file in appropriate language
2217
2218      Gen_Output_File_Ada (Filename, Elab_Order);
2219   end Gen_Output_File;
2220
2221   -------------------------
2222   -- Gen_Output_File_Ada --
2223   -------------------------
2224
2225   procedure Gen_Output_File_Ada
2226     (Filename : String; Elab_Order : Unit_Id_Array)
2227   is
2228      Ada_Main : constant String := Get_Ada_Main_Name;
2229      --  Name to be used for generated Ada main program. See the body of
2230      --  function Get_Ada_Main_Name for details on the form of the name.
2231
2232      Needs_Library_Finalization : constant Boolean :=
2233        not Configurable_Run_Time_On_Target
2234        and then Has_Finalizer (Elab_Order);
2235      --  For restricted run-time libraries (ZFP and Ravenscar) tasks are
2236      --  non-terminating, so we do not want finalization.
2237
2238      Bfiles : Name_Id;
2239      --  Name of generated bind file (spec)
2240
2241      Bfileb : Name_Id;
2242      --  Name of generated bind file (body)
2243
2244   begin
2245      --  Create spec first
2246
2247      Create_Binder_Output (Filename, 's', Bfiles);
2248
2249      --  We always compile the binder file in Ada 95 mode so that we properly
2250      --  handle use of Ada 2005 keywords as identifiers in Ada 95 mode. None
2251      --  of the Ada 2005 or Ada 2012 constructs are needed by the binder file.
2252
2253      WBI ("pragma Warnings (Off);");
2254      WBI ("pragma Ada_95;");
2255
2256      --  If we are operating in Restrictions (No_Exception_Handlers) mode,
2257      --  then we need to make sure that the binder program is compiled with
2258      --  the same restriction, so that no exception tables are generated.
2259
2260      if Cumulative_Restrictions.Set (No_Exception_Handlers) then
2261         WBI ("pragma Restrictions (No_Exception_Handlers);");
2262      end if;
2263
2264      --  Same processing for Restrictions (No_Exception_Propagation)
2265
2266      if Cumulative_Restrictions.Set (No_Exception_Propagation) then
2267         WBI ("pragma Restrictions (No_Exception_Propagation);");
2268      end if;
2269
2270      --  Same processing for pragma No_Run_Time
2271
2272      if No_Run_Time_Mode then
2273         WBI ("pragma No_Run_Time;");
2274      end if;
2275
2276      --  Generate with of System so we can reference System.Address
2277
2278      WBI ("with System;");
2279
2280      --  Generate with of System.Initialize_Scalars if active
2281
2282      if Initialize_Scalars_Used then
2283         WBI ("with System.Scalar_Values;");
2284      end if;
2285
2286      --  Generate withs of System.Secondary_Stack and System.Parameters to
2287      --  allow the generation of the default-sized secondary stack pool.
2288
2289      if Sec_Stack_Used then
2290         WBI ("with System.Parameters;");
2291         WBI ("with System.Secondary_Stack;");
2292      end if;
2293
2294      Resolve_Binder_Options (Elab_Order);
2295
2296      --  Generate standard with's
2297
2298      if not Suppress_Standard_Library_On_Target then
2299         if CodePeer_Mode then
2300            WBI ("with System.Standard_Library;");
2301         end if;
2302      end if;
2303
2304      WBI ("package " & Ada_Main & " is");
2305
2306      --  Main program case
2307
2308      if Bind_Main_Program then
2309         --  Generate argc/argv stuff unless suppressed
2310
2311         if Command_Line_Args_On_Target
2312           or not Configurable_Run_Time_On_Target
2313         then
2314            WBI ("");
2315            WBI ("   gnat_argc : Integer;");
2316            WBI ("   gnat_argv : System.Address;");
2317            WBI ("   gnat_envp : System.Address;");
2318
2319            --  If the standard library is not suppressed, these variables
2320            --  are in the run-time data area for easy run time access.
2321
2322            if not Suppress_Standard_Library_On_Target then
2323               WBI ("");
2324               WBI ("   pragma Import (C, gnat_argc);");
2325               WBI ("   pragma Import (C, gnat_argv);");
2326               WBI ("   pragma Import (C, gnat_envp);");
2327            end if;
2328         end if;
2329
2330         --  Define exit status. Again in normal mode, this is in the run-time
2331         --  library, and is initialized there, but in the configurable
2332         --  run-time case, the variable is declared and initialized in this
2333         --  file.
2334
2335         WBI ("");
2336
2337         if Configurable_Run_Time_Mode then
2338            if Exit_Status_Supported_On_Target then
2339               WBI ("   gnat_exit_status : Integer := 0;");
2340            end if;
2341
2342         else
2343            WBI ("   gnat_exit_status : Integer;");
2344            WBI ("   pragma Import (C, gnat_exit_status);");
2345         end if;
2346
2347         --  Generate the GNAT_Version and Ada_Main_Program_Name info only for
2348         --  the main program. Otherwise, it can lead under some circumstances
2349         --  to a symbol duplication during the link (for instance when a C
2350         --  program uses two Ada libraries). Also zero terminate the string
2351         --  so that its end can be found reliably at run time.
2352
2353         WBI ("");
2354         WBI ("   GNAT_Version : constant String :=");
2355         WBI ("                    """ & Ver_Prefix &
2356                                   Gnat_Version_String &
2357                                   """ & ASCII.NUL;");
2358         WBI ("   pragma Export (C, GNAT_Version, ""__gnat_version"");");
2359
2360         WBI ("");
2361         Set_String ("   Ada_Main_Program_Name : constant String := """);
2362         Get_Name_String (Units.Table (First_Unit_Entry).Uname);
2363
2364         Set_Main_Program_Name;
2365         Set_String (""" & ASCII.NUL;");
2366
2367         Write_Statement_Buffer;
2368
2369         WBI
2370           ("   pragma Export (C, Ada_Main_Program_Name, " &
2371            """__gnat_ada_main_program_name"");");
2372      end if;
2373
2374      WBI ("");
2375      WBI ("   procedure " & Ada_Init_Name.all & ";");
2376      WBI ("   pragma Export (C, " & Ada_Init_Name.all & ", """ &
2377           Ada_Init_Name.all & """);");
2378
2379      --  If -a has been specified use pragma Linker_Constructor for the init
2380      --  procedure and pragma Linker_Destructor for the final procedure.
2381
2382      if Use_Pragma_Linker_Constructor then
2383         WBI ("   pragma Linker_Constructor (" & Ada_Init_Name.all & ");");
2384      end if;
2385
2386      if not Cumulative_Restrictions.Set (No_Finalization) then
2387         WBI ("");
2388         WBI ("   procedure " & Ada_Final_Name.all & ";");
2389         WBI ("   pragma Export (C, " & Ada_Final_Name.all & ", """ &
2390              Ada_Final_Name.all & """);");
2391
2392         if Use_Pragma_Linker_Constructor then
2393            WBI ("   pragma Linker_Destructor (" & Ada_Final_Name.all & ");");
2394         end if;
2395      end if;
2396
2397      if Bind_Main_Program then
2398
2399         WBI ("");
2400
2401         if Exit_Status_Supported_On_Target then
2402            Set_String ("   function ");
2403         else
2404            Set_String ("   procedure ");
2405         end if;
2406
2407         Set_String (Get_Main_Name);
2408
2409         --  Generate argument list if present
2410
2411         if Command_Line_Args_On_Target then
2412            Write_Statement_Buffer;
2413            WBI ("     (argc : Integer;");
2414            WBI ("      argv : System.Address;");
2415            Set_String
2416                ("      envp : System.Address)");
2417
2418            if Exit_Status_Supported_On_Target then
2419               Write_Statement_Buffer;
2420               WBI ("      return Integer;");
2421            else
2422               Write_Statement_Buffer (";");
2423            end if;
2424
2425         else
2426            if Exit_Status_Supported_On_Target then
2427               Write_Statement_Buffer (" return Integer;");
2428            else
2429               Write_Statement_Buffer (";");
2430            end if;
2431         end if;
2432
2433         WBI ("   pragma Export (C, " & Get_Main_Name & ", """ &
2434           Get_Main_Name & """);");
2435      end if;
2436
2437      --  Generate version numbers for units, only if needed. Be very safe on
2438      --  the condition.
2439
2440      if not Configurable_Run_Time_On_Target
2441        or else System_Version_Control_Used
2442        or else not Bind_Main_Program
2443      then
2444         Gen_Versions;
2445      end if;
2446
2447      Gen_Elab_Order (Elab_Order);
2448
2449      --  Spec is complete
2450
2451      WBI ("");
2452      WBI ("end " & Ada_Main & ";");
2453      Close_Binder_Output;
2454
2455      --  Prepare to write body
2456
2457      Create_Binder_Output (Filename, 'b', Bfileb);
2458
2459      --  We always compile the binder file in Ada 95 mode so that we properly
2460      --  handle use of Ada 2005 keywords as identifiers in Ada 95 mode. None
2461      --  of the Ada 2005/2012 constructs are needed by the binder file.
2462
2463      WBI ("pragma Warnings (Off);");
2464      WBI ("pragma Ada_95;");
2465
2466      --  Output Source_File_Name pragmas which look like
2467
2468      --    pragma Source_File_Name (Ada_Main, Spec_File_Name => "sss");
2469      --    pragma Source_File_Name (Ada_Main, Body_File_Name => "bbb");
2470
2471      --  where sss/bbb are the spec/body file names respectively
2472
2473      Get_Name_String (Bfiles);
2474      Name_Buffer (Name_Len + 1 .. Name_Len + 3) := """);";
2475
2476      WBI ("pragma Source_File_Name (" &
2477           Ada_Main &
2478           ", Spec_File_Name => """ &
2479           Name_Buffer (1 .. Name_Len + 3));
2480
2481      Get_Name_String (Bfileb);
2482      Name_Buffer (Name_Len + 1 .. Name_Len + 3) := """);";
2483
2484      WBI ("pragma Source_File_Name (" &
2485           Ada_Main &
2486           ", Body_File_Name => """ &
2487           Name_Buffer (1 .. Name_Len + 3));
2488
2489      --  Generate pragma Suppress (Overflow_Check). This is needed for recent
2490      --  versions of the compiler which have overflow checks on by default.
2491      --  We do not want overflow checking enabled for the increments of the
2492      --  elaboration variables (since this can cause an unwanted reference to
2493      --  the last chance exception handler for limited run-times).
2494
2495      WBI ("pragma Suppress (Overflow_Check);");
2496
2497      --  Generate with of System.Restrictions to initialize
2498      --  Run_Time_Restrictions.
2499
2500      if System_Restrictions_Used
2501        and not Suppress_Standard_Library_On_Target
2502      then
2503         WBI ("");
2504         WBI ("with System.Restrictions;");
2505      end if;
2506
2507      --  Generate with of Ada.Exceptions if needs library finalization
2508
2509      if Needs_Library_Finalization then
2510         WBI ("with Ada.Exceptions;");
2511      end if;
2512
2513      --  Generate with of System.Elaboration_Allocators if the restriction
2514      --  No_Standard_Allocators_After_Elaboration was present.
2515
2516      if Cumulative_Restrictions.Set
2517           (No_Standard_Allocators_After_Elaboration)
2518      then
2519         WBI ("with System.Elaboration_Allocators;");
2520      end if;
2521
2522      --  Generate start of package body
2523
2524      WBI ("");
2525      WBI ("package body " & Ada_Main & " is");
2526      WBI ("");
2527
2528      --  Generate externals for elaboration entities
2529
2530      Gen_Elab_Externals (Elab_Order);
2531
2532      --  Generate default-sized secondary stacks pool. At least one stack is
2533      --  created and assigned to the environment task if secondary stacks are
2534      --  used by the program.
2535
2536      if Sec_Stack_Used then
2537         Set_String ("   Sec_Default_Sized_Stacks");
2538         Set_String (" : array (1 .. ");
2539         Set_Int (Num_Sec_Stacks);
2540         Set_String (") of aliased System.Secondary_Stack.SS_Stack (");
2541
2542         if Opt.Default_Sec_Stack_Size /= No_Stack_Size then
2543            Set_Int (Opt.Default_Sec_Stack_Size);
2544         else
2545            Set_String ("System.Parameters.Runtime_Default_Sec_Stack_Size");
2546         end if;
2547
2548         Set_String (");");
2549         Write_Statement_Buffer;
2550         WBI ("");
2551      end if;
2552
2553      --  Generate reference
2554
2555      if not CodePeer_Mode then
2556         if not Suppress_Standard_Library_On_Target then
2557
2558            --  Generate Priority_Specific_Dispatching pragma string
2559
2560            Set_String
2561              ("   Local_Priority_Specific_Dispatching : " &
2562               "constant String := """);
2563
2564            for J in 0 .. PSD_Pragma_Settings.Last loop
2565               Set_Char (PSD_Pragma_Settings.Table (J));
2566            end loop;
2567
2568            Set_String (""";");
2569            Write_Statement_Buffer;
2570
2571            --  Generate Interrupt_State pragma string
2572
2573            Set_String ("   Local_Interrupt_States : constant String := """);
2574
2575            for J in 0 .. IS_Pragma_Settings.Last loop
2576               Set_Char (IS_Pragma_Settings.Table (J));
2577            end loop;
2578
2579            Set_String (""";");
2580            Write_Statement_Buffer;
2581            WBI ("");
2582         end if;
2583
2584         if not Suppress_Standard_Library_On_Target then
2585
2586            --  The B.1(39) implementation advice says that the adainit and
2587            --  adafinal routines should be idempotent. Generate a flag to
2588            --  ensure that. This is not needed if we are suppressing the
2589            --  standard library since it would never be referenced.
2590
2591            WBI ("   Is_Elaborated : Boolean := False;");
2592
2593            --  Generate bind environment string
2594
2595            Gen_Bind_Env_String;
2596         end if;
2597
2598         WBI ("");
2599      end if;
2600
2601      --  Generate the adafinal routine unless there is no finalization to do
2602
2603      if not Cumulative_Restrictions.Set (No_Finalization) then
2604         if Needs_Library_Finalization then
2605            Gen_Finalize_Library (Elab_Order);
2606         end if;
2607
2608         Gen_Adafinal;
2609      end if;
2610
2611      Gen_Adainit (Elab_Order);
2612
2613      if Bind_Main_Program then
2614         Gen_Main;
2615      end if;
2616
2617      --  Output object file list and the Ada body is complete
2618
2619      Gen_Object_Files_Options (Elab_Order);
2620
2621      WBI ("");
2622      WBI ("end " & Ada_Main & ";");
2623
2624      Close_Binder_Output;
2625   end Gen_Output_File_Ada;
2626
2627   ----------------------
2628   -- Gen_Restrictions --
2629   ----------------------
2630
2631   procedure Gen_Restrictions is
2632      Count : Integer;
2633
2634   begin
2635      if Suppress_Standard_Library_On_Target
2636        or not System_Restrictions_Used
2637      then
2638         return;
2639      end if;
2640
2641      WBI ("      System.Restrictions.Run_Time_Restrictions :=");
2642      WBI ("        (Set =>");
2643      Set_String      ("          (");
2644
2645      Count := 0;
2646
2647      for J in Cumulative_Restrictions.Set'Range loop
2648         Set_Boolean (Cumulative_Restrictions.Set (J));
2649         Set_String (", ");
2650         Count := Count + 1;
2651
2652         if J /= Cumulative_Restrictions.Set'Last and then Count = 8 then
2653            Write_Statement_Buffer;
2654            Set_String ("           ");
2655            Count := 0;
2656         end if;
2657      end loop;
2658
2659      Set_String_Replace ("),");
2660      Write_Statement_Buffer;
2661      Set_String ("         Value => (");
2662
2663      for J in Cumulative_Restrictions.Value'Range loop
2664         Set_Int (Int (Cumulative_Restrictions.Value (J)));
2665         Set_String (", ");
2666      end loop;
2667
2668      Set_String_Replace ("),");
2669      Write_Statement_Buffer;
2670      WBI ("         Violated =>");
2671      Set_String ("          (");
2672      Count := 0;
2673
2674      for J in Cumulative_Restrictions.Violated'Range loop
2675         Set_Boolean (Cumulative_Restrictions.Violated (J));
2676         Set_String (", ");
2677         Count := Count + 1;
2678
2679         if J /= Cumulative_Restrictions.Set'Last and then Count = 8 then
2680            Write_Statement_Buffer;
2681            Set_String ("           ");
2682            Count := 0;
2683         end if;
2684      end loop;
2685
2686      Set_String_Replace ("),");
2687      Write_Statement_Buffer;
2688      Set_String ("         Count => (");
2689
2690      for J in Cumulative_Restrictions.Count'Range loop
2691         Set_Int (Int (Cumulative_Restrictions.Count (J)));
2692         Set_String (", ");
2693      end loop;
2694
2695      Set_String_Replace ("),");
2696      Write_Statement_Buffer;
2697      Set_String ("         Unknown => (");
2698
2699      for J in Cumulative_Restrictions.Unknown'Range loop
2700         Set_Boolean (Cumulative_Restrictions.Unknown (J));
2701         Set_String (", ");
2702      end loop;
2703
2704      Set_String_Replace ("))");
2705      Set_String (";");
2706      Write_Statement_Buffer;
2707   end Gen_Restrictions;
2708
2709   ------------------
2710   -- Gen_Versions --
2711   ------------------
2712
2713   --  This routine generates lines such as:
2714
2715   --    unnnnn : constant Integer := 16#hhhhhhhh#;
2716   --    pragma Export (C, unnnnn, unam);
2717
2718   --  for each unit, where unam is the unit name suffixed by either B or S for
2719   --  body or spec, with dots replaced by double underscores, and hhhhhhhh is
2720   --  the version number, and nnnnn is a 5-digits serial number.
2721
2722   procedure Gen_Versions is
2723      Ubuf : String (1 .. 6) := "u00000";
2724
2725      procedure Increment_Ubuf;
2726      --  Little procedure to increment the serial number
2727
2728      --------------------
2729      -- Increment_Ubuf --
2730      --------------------
2731
2732      procedure Increment_Ubuf is
2733      begin
2734         for J in reverse Ubuf'Range loop
2735            Ubuf (J) := Character'Succ (Ubuf (J));
2736            exit when Ubuf (J) <= '9';
2737            Ubuf (J) := '0';
2738         end loop;
2739      end Increment_Ubuf;
2740
2741   --  Start of processing for Gen_Versions
2742
2743   begin
2744      WBI ("");
2745
2746      WBI ("   type Version_32 is mod 2 ** 32;");
2747      for U in Units.First .. Units.Last loop
2748         if not Units.Table (U).SAL_Interface
2749           and then (not Bind_For_Library
2750                      or else Units.Table (U).Directly_Scanned)
2751         then
2752            Increment_Ubuf;
2753            WBI ("   " & Ubuf & " : constant Version_32 := 16#" &
2754                 Units.Table (U).Version & "#;");
2755            Set_String ("   pragma Export (C, ");
2756            Set_String (Ubuf);
2757            Set_String (", """);
2758
2759            Get_Name_String (Units.Table (U).Uname);
2760
2761            for K in 1 .. Name_Len loop
2762               if Name_Buffer (K) = '.' then
2763                  Set_Char ('_');
2764                  Set_Char ('_');
2765
2766               elsif Name_Buffer (K) = '%' then
2767                  exit;
2768
2769               else
2770                  Set_Char (Name_Buffer (K));
2771               end if;
2772            end loop;
2773
2774            if Name_Buffer (Name_Len) = 's' then
2775               Set_Char ('S');
2776            else
2777               Set_Char ('B');
2778            end if;
2779
2780            Set_String (""");");
2781            Write_Statement_Buffer;
2782         end if;
2783      end loop;
2784   end Gen_Versions;
2785
2786   ------------------------
2787   -- Get_Main_Unit_Name --
2788   ------------------------
2789
2790   function Get_Main_Unit_Name (S : String) return String is
2791      Result : String := S;
2792
2793   begin
2794      for J in S'Range loop
2795         if Result (J) = '.' then
2796            Result (J) := '_';
2797         end if;
2798      end loop;
2799
2800      return Result;
2801   end Get_Main_Unit_Name;
2802
2803   -----------------------
2804   -- Get_Ada_Main_Name --
2805   -----------------------
2806
2807   function Get_Ada_Main_Name return String is
2808      Suffix : constant String := "_00";
2809      Name   : String (1 .. Opt.Ada_Main_Name.all'Length + Suffix'Length) :=
2810                 Opt.Ada_Main_Name.all & Suffix;
2811      Nlen   : Natural;
2812
2813   begin
2814      --  For CodePeer, we want reproducible names (independent of other mains
2815      --  that may or may not be present) that don't collide when analyzing
2816      --  multiple mains and which are easily recognizable as "ada_main" names.
2817
2818      if CodePeer_Mode then
2819         Get_Name_String (Units.Table (First_Unit_Entry).Uname);
2820
2821         return
2822           "ada_main_for_" &
2823             Get_Main_Unit_Name (Name_Buffer (1 .. Name_Len - 2));
2824      end if;
2825
2826      --  This loop tries the following possibilities in order
2827      --    <Ada_Main>
2828      --    <Ada_Main>_01
2829      --    <Ada_Main>_02
2830      --    ..
2831      --    <Ada_Main>_99
2832      --  where <Ada_Main> is equal to Opt.Ada_Main_Name. By default,
2833      --  it is set to 'ada_main'.
2834
2835      for J in 0 .. 99 loop
2836         if J = 0 then
2837            Nlen := Name'Length - Suffix'Length;
2838         else
2839            Nlen := Name'Length;
2840            Name (Name'Last) := Character'Val (J mod 10 + Character'Pos ('0'));
2841            Name (Name'Last - 1) :=
2842              Character'Val (J /   10 + Character'Pos ('0'));
2843         end if;
2844
2845         for K in ALIs.First .. ALIs.Last loop
2846            for L in ALIs.Table (K).First_Unit .. ALIs.Table (K).Last_Unit loop
2847
2848               --  Get unit name, removing %b or %e at end
2849
2850               Get_Name_String (Units.Table (L).Uname);
2851               Name_Len := Name_Len - 2;
2852
2853               if Name_Buffer (1 .. Name_Len) = Name (1 .. Nlen) then
2854                  goto Continue;
2855               end if;
2856            end loop;
2857         end loop;
2858
2859         return Name (1 .. Nlen);
2860
2861      <<Continue>>
2862         null;
2863      end loop;
2864
2865      --  If we fall through, just use a peculiar unlikely name
2866
2867      return ("Qwertyuiop");
2868   end Get_Ada_Main_Name;
2869
2870   -------------------
2871   -- Get_Main_Name --
2872   -------------------
2873
2874   function Get_Main_Name return String is
2875   begin
2876      --  Explicit name given with -M switch
2877
2878      if Bind_Alternate_Main_Name then
2879         return Alternate_Main_Name.all;
2880
2881      --  Case of main program name to be used directly
2882
2883      elsif Use_Ada_Main_Program_Name_On_Target then
2884
2885         --  Get main program name
2886
2887         Get_Name_String (Units.Table (First_Unit_Entry).Uname);
2888
2889         --  If this is a child name, return only the name of the child, since
2890         --  we can't have dots in a nested program name. Note that we do not
2891         --  include the %b at the end of the unit name.
2892
2893         for J in reverse 1 .. Name_Len - 2 loop
2894            if J = 1 or else Name_Buffer (J - 1) = '.' then
2895               return Name_Buffer (J .. Name_Len - 2);
2896            end if;
2897         end loop;
2898
2899         raise Program_Error; -- impossible exit
2900
2901      --  Case where "main" is to be used as default
2902
2903      else
2904         return "main";
2905      end if;
2906   end Get_Main_Name;
2907
2908   ---------------------
2909   -- Get_WC_Encoding --
2910   ---------------------
2911
2912   function Get_WC_Encoding return Character is
2913   begin
2914      --  If encoding method specified by -W switch, then return it
2915
2916      if Wide_Character_Encoding_Method_Specified then
2917         return WC_Encoding_Letters (Wide_Character_Encoding_Method);
2918
2919      --  If no main program, and not specified, set brackets, we really have
2920      --  no better choice. If some other encoding is required when there is
2921      --  no main, it must be set explicitly using -Wx.
2922
2923      --  Note: if the ALI file always passed the wide character encoding of
2924      --  every file, then we could use the encoding of the initial specified
2925      --  file, but this information is passed only for potential main
2926      --  programs. We could fix this sometime, but it is a very minor point
2927      --  (wide character default encoding for [Wide_[Wide_]]Text_IO when there
2928      --  is no main program).
2929
2930      elsif No_Main_Subprogram then
2931         return 'b';
2932
2933      --  Otherwise if there is a main program, take encoding from it
2934
2935      else
2936         return ALIs.Table (ALIs.First).WC_Encoding;
2937      end if;
2938   end Get_WC_Encoding;
2939
2940   -------------------
2941   -- Has_Finalizer --
2942   -------------------
2943
2944   function Has_Finalizer (Elab_Order : Unit_Id_Array) return Boolean is
2945      U     : Unit_Record;
2946      Unum  : Unit_Id;
2947
2948   begin
2949      for E in reverse Elab_Order'Range loop
2950         Unum := Elab_Order (E);
2951         U    := Units.Table (Unum);
2952
2953         --  We are only interested in non-generic packages
2954
2955         if U.Unit_Kind = 'p'
2956           and then U.Has_Finalizer
2957           and then not U.Is_Generic
2958           and then not U.No_Elab
2959         then
2960            return True;
2961         end if;
2962      end loop;
2963
2964      return False;
2965   end Has_Finalizer;
2966
2967   ----------
2968   -- Hash --
2969   ----------
2970
2971   function Hash (Nam : Name_Id) return Header_Num is
2972   begin
2973      return Int (Nam - Names_Low_Bound) rem Header_Num'Last;
2974   end Hash;
2975
2976   ----------------------
2977   -- Lt_Linker_Option --
2978   ----------------------
2979
2980   function Lt_Linker_Option (Op1 : Natural; Op2 : Natural) return Boolean is
2981   begin
2982      --  Sort internal files last
2983
2984      if Linker_Options.Table (Op1).Internal_File
2985           /=
2986         Linker_Options.Table (Op2).Internal_File
2987      then
2988         --  Note: following test uses False < True
2989
2990         return Linker_Options.Table (Op1).Internal_File
2991                  <
2992                Linker_Options.Table (Op2).Internal_File;
2993
2994      --  If both internal or both non-internal, sort according to the
2995      --  elaboration position. A unit that is elaborated later should come
2996      --  earlier in the linker options list.
2997
2998      else
2999         return Units.Table (Linker_Options.Table (Op1).Unit).Elab_Position
3000                  >
3001                Units.Table (Linker_Options.Table (Op2).Unit).Elab_Position;
3002      end if;
3003   end Lt_Linker_Option;
3004
3005   ------------------------
3006   -- Move_Linker_Option --
3007   ------------------------
3008
3009   procedure Move_Linker_Option (From : Natural; To : Natural) is
3010   begin
3011      Linker_Options.Table (To) := Linker_Options.Table (From);
3012   end Move_Linker_Option;
3013
3014   ----------------------------
3015   -- Resolve_Binder_Options --
3016   ----------------------------
3017
3018   procedure Resolve_Binder_Options (Elab_Order : Unit_Id_Array) is
3019      procedure Check_Package (Var : in out Boolean; Name : String);
3020      --  Set Var to true iff the current identifier in Namet is Name. Do
3021      --  nothing if it doesn't match. This procedure is just a helper to
3022      --  avoid explicitly dealing with length.
3023
3024      -------------------
3025      -- Check_Package --
3026      -------------------
3027
3028      procedure Check_Package (Var : in out Boolean; Name : String) is
3029      begin
3030         if Name_Len = Name'Length
3031           and then Name_Buffer (1 .. Name_Len) = Name
3032         then
3033            Var := True;
3034         end if;
3035      end Check_Package;
3036
3037   --  Start of processing for Resolve_Binder_Options
3038
3039   begin
3040      for E in Elab_Order'Range loop
3041         Get_Name_String (Units.Table (Elab_Order (E)).Uname);
3042
3043         --  This is not a perfect approach, but is the current protocol
3044         --  between the run-time and the binder to indicate that tasking is
3045         --  used: System.OS_Interface should always be used by any tasking
3046         --  application.
3047
3048         Check_Package (With_GNARL, "system.os_interface%s");
3049
3050         --  Ditto for the use of restricted tasking
3051
3052         Check_Package
3053           (System_Tasking_Restricted_Stages_Used,
3054            "system.tasking.restricted.stages%s");
3055
3056         --  Ditto for the use of interrupts
3057
3058         Check_Package (System_Interrupts_Used, "system.interrupts%s");
3059
3060         --  Ditto for the use of dispatching domains
3061
3062         Check_Package
3063           (Dispatching_Domains_Used,
3064            "system.multiprocessors.dispatching_domains%s");
3065
3066         --  Ditto for the use of restrictions
3067
3068         Check_Package (System_Restrictions_Used, "system.restrictions%s");
3069
3070         --  Ditto for the use of System.Secondary_Stack
3071
3072         Check_Package
3073           (System_Secondary_Stack_Used, "system.secondary_stack%s");
3074
3075         --  Ditto for use of an SMP bareboard runtime
3076
3077         Check_Package (System_BB_CPU_Primitives_Multiprocessors_Used,
3078                        "system.bb.cpu_primitives.multiprocessors%s");
3079
3080         --  Ditto for System.Version_Control, which is used for Version and
3081         --  Body_Version attributes.
3082
3083         Check_Package (System_Version_Control_Used,
3084                        "system.version_control%s");
3085      end loop;
3086   end Resolve_Binder_Options;
3087
3088   ------------------
3089   -- Set_Bind_Env --
3090   ------------------
3091
3092   procedure Set_Bind_Env (Key, Value : String) is
3093   begin
3094      --  The lengths of Key and Value are stored as single bytes
3095
3096      if Key'Length > 255 then
3097         Osint.Fail ("bind environment key """ & Key & """ too long");
3098      end if;
3099
3100      if Value'Length > 255 then
3101         Osint.Fail ("bind environment value """ & Value & """ too long");
3102      end if;
3103
3104      Bind_Environment.Set (Name_Find (Key), Name_Find (Value));
3105   end Set_Bind_Env;
3106
3107   -----------------
3108   -- Set_Boolean --
3109   -----------------
3110
3111   procedure Set_Boolean (B : Boolean) is
3112      False_Str : constant String := "False";
3113      True_Str  : constant String := "True";
3114
3115   begin
3116      if B then
3117         Statement_Buffer (Stm_Last + 1 .. Stm_Last + True_Str'Length) :=
3118           True_Str;
3119         Stm_Last := Stm_Last + True_Str'Length;
3120      else
3121         Statement_Buffer (Stm_Last + 1 .. Stm_Last + False_Str'Length) :=
3122           False_Str;
3123         Stm_Last := Stm_Last + False_Str'Length;
3124      end if;
3125   end Set_Boolean;
3126
3127   --------------
3128   -- Set_Char --
3129   --------------
3130
3131   procedure Set_Char (C : Character) is
3132   begin
3133      Stm_Last := Stm_Last + 1;
3134      Statement_Buffer (Stm_Last) := C;
3135   end Set_Char;
3136
3137   -------------
3138   -- Set_Int --
3139   -------------
3140
3141   procedure Set_Int (N : Int) is
3142   begin
3143      if N < 0 then
3144         Set_String ("-");
3145         Set_Int (-N);
3146
3147      else
3148         if N > 9 then
3149            Set_Int (N / 10);
3150         end if;
3151
3152         Stm_Last := Stm_Last + 1;
3153         Statement_Buffer (Stm_Last) :=
3154           Character'Val (N mod 10 + Character'Pos ('0'));
3155      end if;
3156   end Set_Int;
3157
3158   -------------------------
3159   -- Set_IS_Pragma_Table --
3160   -------------------------
3161
3162   procedure Set_IS_Pragma_Table is
3163   begin
3164      for F in ALIs.First .. ALIs.Last loop
3165         for K in ALIs.Table (F).First_Interrupt_State ..
3166                  ALIs.Table (F).Last_Interrupt_State
3167         loop
3168            declare
3169               Inum : constant Int :=
3170                        Interrupt_States.Table (K).Interrupt_Id;
3171               Stat : constant Character :=
3172                        Interrupt_States.Table (K).Interrupt_State;
3173
3174            begin
3175               while IS_Pragma_Settings.Last < Inum loop
3176                  IS_Pragma_Settings.Append ('n');
3177               end loop;
3178
3179               IS_Pragma_Settings.Table (Inum) := Stat;
3180            end;
3181         end loop;
3182      end loop;
3183   end Set_IS_Pragma_Table;
3184
3185   ---------------------------
3186   -- Set_Main_Program_Name --
3187   ---------------------------
3188
3189   procedure Set_Main_Program_Name is
3190   begin
3191      --  Note that name has %b on the end which we ignore
3192
3193      --  First we output the initial _ada_ since we know that the main program
3194      --  is a library level subprogram.
3195
3196      Set_String ("_ada_");
3197
3198      --  Copy name, changing dots to double underscores
3199
3200      for J in 1 .. Name_Len - 2 loop
3201         if Name_Buffer (J) = '.' then
3202            Set_String ("__");
3203         else
3204            Set_Char (Name_Buffer (J));
3205         end if;
3206      end loop;
3207   end Set_Main_Program_Name;
3208
3209   ---------------------
3210   -- Set_Name_Buffer --
3211   ---------------------
3212
3213   procedure Set_Name_Buffer is
3214   begin
3215      for J in 1 .. Name_Len loop
3216         Set_Char (Name_Buffer (J));
3217      end loop;
3218   end Set_Name_Buffer;
3219
3220   -------------------------
3221   -- Set_PSD_Pragma_Table --
3222   -------------------------
3223
3224   procedure Set_PSD_Pragma_Table is
3225   begin
3226      for F in ALIs.First .. ALIs.Last loop
3227         for K in ALIs.Table (F).First_Specific_Dispatching ..
3228                  ALIs.Table (F).Last_Specific_Dispatching
3229         loop
3230            declare
3231               DTK : Specific_Dispatching_Record
3232                       renames Specific_Dispatching.Table (K);
3233
3234            begin
3235               while PSD_Pragma_Settings.Last < DTK.Last_Priority loop
3236                  PSD_Pragma_Settings.Append ('F');
3237               end loop;
3238
3239               for Prio in DTK.First_Priority .. DTK.Last_Priority loop
3240                  PSD_Pragma_Settings.Table (Prio) := DTK.Dispatching_Policy;
3241               end loop;
3242            end;
3243         end loop;
3244      end loop;
3245   end Set_PSD_Pragma_Table;
3246
3247   ----------------
3248   -- Set_String --
3249   ----------------
3250
3251   procedure Set_String (S : String) is
3252   begin
3253      Statement_Buffer (Stm_Last + 1 .. Stm_Last + S'Length) := S;
3254      Stm_Last := Stm_Last + S'Length;
3255   end Set_String;
3256
3257   ------------------------
3258   -- Set_String_Replace --
3259   ------------------------
3260
3261   procedure Set_String_Replace (S : String) is
3262   begin
3263      Statement_Buffer (Stm_Last - S'Length + 1 .. Stm_Last) := S;
3264   end Set_String_Replace;
3265
3266   -------------------
3267   -- Set_Unit_Name --
3268   -------------------
3269
3270   procedure Set_Unit_Name is
3271   begin
3272      for J in 1 .. Name_Len - 2 loop
3273         if Name_Buffer (J) = '.' then
3274            Set_String ("__");
3275         else
3276            Set_Char (Name_Buffer (J));
3277         end if;
3278      end loop;
3279   end Set_Unit_Name;
3280
3281   ---------------------
3282   -- Set_Unit_Number --
3283   ---------------------
3284
3285   procedure Set_Unit_Number (U : Unit_Id) is
3286      Num_Units : constant Nat := Nat (Units.Last) - Nat (Unit_Id'First);
3287      Unum      : constant Nat := Nat (U) - Nat (Unit_Id'First);
3288
3289   begin
3290      if Num_Units >= 10 and then Unum < 10 then
3291         Set_Char ('0');
3292      end if;
3293
3294      if Num_Units >= 100 and then Unum < 100 then
3295         Set_Char ('0');
3296      end if;
3297
3298      Set_Int (Unum);
3299   end Set_Unit_Number;
3300
3301   ---------------------
3302   -- Write_Bind_Line --
3303   ---------------------
3304
3305   procedure Write_Bind_Line (S : String) is
3306   begin
3307      --  Need to strip trailing LF from S
3308
3309      WBI (S (S'First .. S'Last - 1));
3310   end Write_Bind_Line;
3311
3312   ----------------------------
3313   -- Write_Statement_Buffer --
3314   ----------------------------
3315
3316   procedure Write_Statement_Buffer is
3317   begin
3318      WBI (Statement_Buffer (1 .. Stm_Last));
3319      Stm_Last := 0;
3320   end Write_Statement_Buffer;
3321
3322   procedure Write_Statement_Buffer (S : String) is
3323   begin
3324      Set_String (S);
3325      Write_Statement_Buffer;
3326   end Write_Statement_Buffer;
3327
3328end Bindgen;
3329