home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
gnat-2.06-src.tgz
/
tar.out
/
fsf
/
gnat
/
ada
/
bindgen.adb
< prev
next >
Wrap
Text File
|
1996-09-28
|
11KB
|
342 lines
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- B I N D G E N --
-- --
-- B o d y --
-- --
-- $Revision: 1.39 $ --
-- --
-- Copyright (c) 1992,1993,1994 NYU, All Rights Reserved --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 2, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING. If not, write --
-- to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
-- --
------------------------------------------------------------------------------
with ALI; use ALI;
with Binde; use Binde;
with Namet; use Namet;
with Opt; use Opt;
with Osint; use Osint;
with Types; use Types;
package body Bindgen is
Statement_Buffer : String (1 .. 1000);
-- Buffer used for constructing output statements
With_Finalization : Boolean := False;
-- Flag which indicates whether the program use finalization
-- (presence of the unit System.Finalization_Implementation)
-----------------------
-- Local Subprograms --
-----------------------
procedure Gen_Elab_Calls;
-- Generate sequence of elaboration calls
procedure Gen_Main_Program_File;
-- Generate lines for output file in main program case
procedure Gen_Non_Main_Program_File;
-- Generate lines for output file in non-main program case
procedure List_Object_Files_Options;
-- Output a comment containing a list of the full names of the object
-- files to be linked and the list of linker options supplised by
-- Linker_Options pragmas in the source.
procedure List_Versions;
-- Output series of definitions for unit versions
---------------------
-- Gen_Output_File --
---------------------
procedure Gen_Output_File is
begin
Create_Binder_Output;
if Bind_Main_Program then
Gen_Main_Program_File;
else
Gen_Non_Main_Program_File;
end if;
Close_Binder_Output;
end Gen_Output_File;
--------------------
-- Gen_Elab_Calls --
--------------------
procedure Gen_Elab_Calls is
L : Natural;
Col : Natural;
begin
for E in Elab_Order.First .. Elab_Order.Last loop
Get_Name_String (Unit.Table (Elab_Order.Table (E)).Uname);
-- if the program uses finalization we must make sure to finalize
-- global objects too at the end of the program.
if Name_Buffer (1 .. 34) = "system.finalization_implementation" then
With_Finalization := True;
end if;
-- Generate elaboration call if elaboration needed
if not Unit.Table (Elab_Order.Table (E)).No_Elab then
Statement_Buffer (1 .. 3) := " ";
-- Copy the unit name (and replace '.' by '__' for child unit)
L := 4;
for J in 1 .. Name_Len - 2 loop
if Name_Buffer (J) /= '.' then
Statement_Buffer (L) := Name_Buffer (J);
L := L + 1;
else
Statement_Buffer (L .. L + 1) := "__";
L := L + 2;
end if;
end loop;
-- Complete call to elaboration routine
Statement_Buffer (L .. L + 6) := "___elab";
Statement_Buffer (L + 7) := Name_Buffer (Name_Len);
Statement_Buffer (L + 8 .. L + 11) := " ();";
L := L + 11;
Write_Binder_Info (Statement_Buffer (1 .. L));
end if;
end loop;
end Gen_Elab_Calls;
---------------------------
-- Gen_Main_Program_File --
---------------------------
procedure Gen_Main_Program_File is
begin
-- Generate __main_priority function
declare
Ctr : Integer;
P : Int;
procedure Set_Int (N : Nat);
-- Set given value in decimal in Statement_Buffer with no spaces
procedure Set_Int (N : Nat) is
begin
if N > 9 then
Set_Int (N / 10);
else
Statement_Buffer (Ctr) :=
Character'Val (N mod 10 + Character'Pos ('0'));
Ctr := Ctr + 1;
end if;
end Set_Int;
begin
Write_Binder_Info ("int");
Write_Binder_Info ("__main_priority ()");
Write_Binder_Info ("{");
Statement_Buffer (1 .. 9) := " return ";
Ctr := 10;
P := ALIs.Table (ALIs.First).Main_Priority;
if P < 0 then
P := -P;
Statement_Buffer (Ctr) := '-';
Ctr := Ctr + 1;
end if;
Set_Int (P);
Statement_Buffer (Ctr) := ';';
Write_Binder_Info (Statement_Buffer (1 .. Ctr));
Write_Binder_Info ("}");
end;
Write_Binder_Info ("extern int gnat_argc;");
Write_Binder_Info ("extern char **gnat_argv;");
Write_Binder_Info ("extern int gnat_exit_status;");
-- Generate main
-- (which gcc bitches about if it returns anything but int)
if ALIs.Table (ALIs.First).Main_Program = Proc then
Write_Binder_Info ("int main (argc, argv)");
else
Write_Binder_Info ("int main (argc, argv)");
end if;
Write_Binder_Info (" int argc;");
Write_Binder_Info (" char **argv;");
Write_Binder_Info ("{");
Write_Binder_Info (" gnat_argc = argc;");
Write_Binder_Info (" gnat_argv = argv;");
Write_Binder_Info (" ");
Write_Binder_Info (" __gnat_initialize();");
Gen_Elab_Calls;
Write_Binder_Info (" ");
Get_Name_String (Unit.Table (First_Unit_Entry).Uname);
-- Main program is procedure case
if ALIs.Table (ALIs.First).Main_Program = Proc then
Statement_Buffer (1 .. 8) := " _ada_";
Statement_Buffer (9 .. Name_Len + 6) :=
Name_Buffer (1 .. Name_Len - 2);
Statement_Buffer (Name_Len + 7 .. Name_Len + 10) := " ();";
Write_Binder_Info (Statement_Buffer (1 .. Name_Len + 10));
-- Main program is function case
else -- ALIs.Table (ALIs_First).Main_Program = Func
Statement_Buffer (1 .. 16) := " return (_ada_";
Statement_Buffer (17 .. Name_Len + 14) :=
Name_Buffer (1 .. Name_Len - 2);
Statement_Buffer (Name_Len + 15 .. Name_Len + 19) := " ());";
Write_Binder_Info (Statement_Buffer (1 .. Name_Len + 19));
end if;
if With_Finalization then
Write_Binder_Info (" system__finalization_implementation"
& "__finalize_global_list ();");
end if;
Write_Binder_Info (" __gnat_finalize();");
Write_Binder_Info (" exit (gnat_exit_status);");
Write_Binder_Info ("}");
List_Versions;
List_Object_Files_Options;
end Gen_Main_Program_File;
-------------------------------
-- Gen_Non_Main_Program_File --
-------------------------------
procedure Gen_Non_Main_Program_File is
begin
Write_Binder_Info ("void ada__bind ()");
Write_Binder_Info ("{");
Gen_Elab_Calls;
Write_Binder_Info ("}");
List_Versions;
List_Object_Files_Options;
end Gen_Non_Main_Program_File;
-------------------------------
-- List_Object_Files_Options --
-------------------------------
procedure List_Object_Files_Options is
Sptr : Natural;
begin
Write_Binder_Info ("/* BEGIN Object file/option list");
for E in Elab_Order.First .. Elab_Order.Last loop
Get_Name_String (Unit.Table (Elab_Order.Table (E)).Uname);
-- If not spec that has an associated body, then generate a
-- comment giving the name of the corresponding ALI file
if Unit.Table (Elab_Order.Table (E)).Utype /= Is_Spec then
-- Now output the file name as a comment
Get_Name_String
(ALIs.Table
(Unit.Table (Elab_Order.Table (E)).My_ALI).Ofile_Full_Name);
Write_Binder_Info (Name_Buffer (1 .. Name_Len));
end if;
end loop;
-- Write linker options
Sptr := 0;
for J in 1 .. Linker_Options.Last loop
if Linker_Options.Table (J) = Ascii.Nul then
Write_Binder_Info (Statement_Buffer (1 .. Sptr));
Sptr := 0;
else
Sptr := Sptr + 1;
Statement_Buffer (Sptr) := Linker_Options.Table (J);
end if;
end loop;
Write_Binder_Info (" END Object file/option list */");
end List_Object_Files_Options;
-------------------
-- List_Versions --
-------------------
-- This routine generates a line of the form:
-- unsigned unam = 0xhhhhhhhh;
-- for each unit, where unam is the unit name suffixed by either B or
-- S for body or spec, with dots replaced by double underscores.
procedure List_Versions is
Sptr : Natural;
begin
for U in Unit.First .. Unit.Last loop
Statement_Buffer (1 .. 9) := "unsigned ";
Sptr := 10;
Get_Name_String (Unit.Table (U).Uname);
for K in 1 .. Name_Len loop
if Name_Buffer (K) = '.' then
Statement_Buffer (Sptr) := '_';
Sptr := Sptr + 1;
Name_Buffer (K) := '_';
elsif Name_Buffer (K) = '%' then
exit;
end if;
Statement_Buffer (Sptr) := Name_Buffer (K);
Sptr := Sptr + 1;
end loop;
if Name_Buffer (Name_Len) = 's' then
Statement_Buffer (Sptr) := 'S';
else
Statement_Buffer (Sptr) := 'B';
end if;
Sptr := Sptr + 1;
Statement_Buffer (Sptr .. Sptr + 4) := " = 0x";
Sptr := Sptr + 5;
Statement_Buffer (Sptr .. Sptr + 7) := Unit.Table (U).Version;
Statement_Buffer (Sptr + 8) := ';';
Write_Binder_Info (Statement_Buffer (1 .. Sptr + 8));
end loop;
end List_Versions;
end Bindgen;