The RM B.1 (39) implementation advice says that the adainit/adafinal routines
generated to manage Ada libraries from foreign languages should be idempotent.
This adds an elaboration flag to the file generated by the binder and an early
return to the routines to ensure that this is the case.

Tested on x86_64-pc-linux-gnu, committed on trunk

2011-08-04  Eric Botcazou  <ebotca...@adacore.com>

        * bindgen.adb (Gen_Adafinal_Ada): Generate an early return if the
        library has already been finalized.
        (Gen_Adafinal_C): Likewise.
        (Gen_Adainit_Ada): Generate an early return if the library has
        already been elaborated.
        (Gen_Adainit_C): Likewise.
        (Gen_Output_File_Ada): Generate an elaboration flag.
        (Gen_Output_File_C): Likewise.

Index: bindgen.adb
===================================================================
--- bindgen.adb (revision 177329)
+++ bindgen.adb (working copy)
@@ -428,8 +428,20 @@
    begin
       WBI ("   procedure " & Ada_Final_Name.all & " is");
 
+      if Bind_Main_Program and then VM_Target = No_VM then
+         WBI ("      procedure s_stalib_adafinal;");
+         Set_String ("      pragma Import (C, s_stalib_adafinal, ");
+         Set_String ("""system__standard_library__adafinal"");");
+         Write_Statement_Buffer;
+      end if;
+
+      WBI ("   begin");
+      WBI ("      if not Is_Elaborated then");
+      WBI ("         return;");
+      WBI ("      end if;");
+      WBI ("      Is_Elaborated := False;");
+
       if not Bind_Main_Program then
-         WBI ("   begin");
          if Lib_Final_Built then
             WBI ("      finalize_library;");
          else
@@ -439,17 +451,12 @@
       --  Main program case
 
       elsif VM_Target = No_VM then
-         WBI ("      procedure s_stalib_adafinal;");
-         WBI ("      pragma Import (C, s_stalib_adafinal, " &
-              """system__standard_library__adafinal"");");
-         WBI ("   begin");
          WBI ("      s_stalib_adafinal;");
 
       --  Pragma Import C cannot be used on virtual machine targets, therefore
       --  call the runtime finalization routine directly.
 
       else
-         WBI ("   begin");
          WBI ("      System.Standard_Library.Adafinal;");
       end if;
 
@@ -465,6 +472,10 @@
    begin
       WBI ("void " & Ada_Final_Name.all & " (void) {");
 
+      WBI ("   if (!is_elaborated)");
+      WBI ("      return;");
+      WBI ("   is_elaborated = 0;");
+
       if not Bind_Main_Program then
          if Lib_Final_Built then
             WBI ("   finalize_library ();");
@@ -685,6 +696,11 @@
 
          WBI ("   begin");
 
+         WBI ("      if Is_Elaborated then");
+         WBI ("         return;");
+         WBI ("      end if;");
+         WBI ("      Is_Elaborated := True;");
+
          Set_String ("      Main_Priority := ");
          Set_Int    (Main_Priority);
          Set_Char   (';');
@@ -941,6 +957,10 @@
       WBI ("void " & Ada_Init_Name.all & " (void)");
       WBI ("{");
 
+      WBI ("   if (is_elaborated)");
+      WBI ("      return;");
+      WBI ("   is_elaborated = 1;");
+
       --  Standard library suppressed
 
       if Suppress_Standard_Library_On_Target then
@@ -3077,6 +3097,9 @@
          WBI ("");
       end if;
 
+      WBI ("   Is_Elaborated : Boolean := False;");
+      WBI ("");
+
       --  Generate the adafinal routine unless there is no finalization to do
 
       if not Cumulative_Restrictions.Set (No_Finalization) then
@@ -3300,6 +3323,9 @@
          WBI ("");
       end if;
 
+      WBI ("static char is_elaborated = 0;");
+      WBI ("");
+
       --  Generate the adafinal routine unless there is no finalization to do
 
       if not Cumulative_Restrictions.Set (No_Finalization) then

Reply via email to