OSDN Git Service

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