OSDN Git Service

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