comp.lang.ada
 help / color / mirror / Atom feed
From: rod.chapman@praxis-cs.co.uk (Rod Chapman)
Subject: Re: [Spark] Arrays of Strings
Date: 11 Apr 2003 05:32:00 -0700
Date: 2003-04-11T12:32:00+00:00	[thread overview]
Message-ID: <cf2c6063.0304110211.596b6b2b@posting.google.com> (raw)
In-Reply-To: slrnb95ehu.ob.lutz@taranis.iks-jena.de

Lutz Donnerhacke <lutz@iks-jena.de> wrote in message news:<slrnb95ehu.ob.lutz@taranis.iks-jena.de>...
> In order to implement thin an execve binding, I wonder how to emulate the
> C-Type "char const * const x []". Any bright ideas?


Lutz and others,
  Here are some thoughts and a possible solution to this problem.
The execve() API is indeed a complex one for SPARK, since the
type "pointer to unconstrained array of pointer to null terminated
C String" is a tricky one for SPARK to model.

 The trick with bindings like this is to come up with a package
specification which is pure SPARK, and presents a clean,
elegant model to the outside world.  No details of the
C type model, or the "glue" needed to bind the two languages
together should be allowed to leak into the package spec!
All the glue and C-related stuff should be hidden in the body.

I'm also working on the assumption that Lutz wants a binding
that is as "thin" as possible, and there are good reasons
to support this approach.

Let's look at how the GNAT.OS_Lib does it...a few fragments:

   type String_Access is access all String;
   type String_List is array (Positive range <>) of String_Access;
   subtype Argument_List is String_List;

   procedure Spawn
     (Program_Name : String;
      Args         : Argument_List;
      Success      : out Boolean);

OK - reasonably elegant, but unfortunately not much use
in this context, since SPARK does not allow explicit declaration
of access types.

The trick here (thanks to Tucker Taft here, who just thought of this
during lunch...) is to change the abstraction a bit to make the
"Args" parameter a legal SPARK type...

I suggest using a single String parameter, where distinct arguments
are separated and terminated by a special character.  ASCII.Nul
is probably a good choice!

So...the SPARK-friendly package spec looks something like:

  package Kernel
  --# own State;
  --# initializes State;
  is
     -- "Args" is a list of arguments, each of which is
     -- termianted by ASCII.Nul
     --
     -- For Example
     --   Kernel.Spawn (Program_Name => "gcc",
     --                 Args         => "-c" & ASCII.Nul &
     --                                 "-g" & ASCII.Nul &
     --                                 "spark.adb" & ASCII.Nul,
     --                 Success      => Success);

     procedure Spawn (Program_Name : in     String;
                      Args         : in     String;
                      Success      :    out Boolean);
     --# global in out State;
     --# derives Success from State, Program_Name, Args &
     --#         State from *, Program_Name, Args;

  end Kernel;

This meets our requirements - perfectly legal SPARK, and none of the
C-related glue is visible.

The body is Ada95 (not SPARK), and uses the facilities of Annex B and
Interfaces to do its stuff.  I've left out a few details but it
goes something like:

   with Interfaces;
   with Interfaces.C;
   with Interfaces.C.Strings;
   use type Interfaces.C.Char;
   use type Interfaces.C.Size_T;
   use type Interfaces.C.Int;
   package body Kernel
   is

     package C renames Interfaces.C;

     -- Count the number of Nul-terminated argments in a given
String...
     function Number_of_Args (Args : in String) return C.Size_T
     is
     begin
       return 2;
     end Number_of_Args;

     procedure Spawn (Program_Name : in     String;
                      Args         : in     String;
                      Success      :    out Boolean)
     is
        subtype Args_Count is C.size_t range 1 .. Number_Of_Args
(Args);
        type Args_Ptr_Vector is array (Args_Count) of aliased
C.Strings.Chars_Ptr;
        Args_Ptrs      : Args_Ptr_Vector;

        subtype C_Args_Index is C.size_t range C.Size_T(Args'First) ..
C.Size_T(Args'Last);
        subtype C_Args_Type  is C.char_array (C_Args_Index);
        C_Args         : C_Args_Type := C.To_C (Args, False);

        C_Program_Name : C.Strings.chars_ptr;
        Ret            : C.Int;

        -- Bind to C here - I've missed out envp here for
simplicity...
        function Execve (Filename : in C.Strings.Chars_Ptr;
                         Argv     : in C.Strings.Chars_Ptr) return
C.Int;
        pragma Import (C, Execve);

        -- Sets the elements of Args_Ptrs to be the 'Access
        -- of each of the N arguments contained in C_Args...
        procedure Set_Args_Ptrs
        --# global out Args_Ptrs;
        --#        in  C_Args;
        is
        begin
           -- proof left to reader... :-)
           null;
        end Set_Args_Ptrs;


     begin
        C_Args := C.To_C (Args, False);

        Set_Args_Ptrs;

        C_Program_Name := C.Strings.New_String (Program_Name);

        Ret := Execve (C_Program_Name, Args_Ptrs (1)'Access);

        C.Strings.Free (C_Program_Name);

        Success := (Ret = 0); -- or something like that...
     end Spawn;
  end Kernel;



  parent reply	other threads:[~2003-04-11 12:32 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-04-08 12:02 [Spark] Arrays of Strings Lutz Donnerhacke
2003-04-08 18:08 ` Martin Krischik
2003-04-09  9:23   ` Lutz Donnerhacke
2003-04-09 12:38     ` Hyman Rosen
2003-04-09 12:47       ` Vinzent Hoefler
2003-04-09 14:27         ` Hyman Rosen
2003-04-09 15:13           ` Vinzent Hoefler
2003-04-09 17:21         ` Hyman Rosen
2003-04-09 18:41           ` Vinzent Hoefler
2003-04-09 21:04           ` Randy Brukardt
2003-04-10 23:21           ` John R. Strohm
2003-04-11 12:19             ` Hyman Rosen
2003-04-11 13:14               ` John R. Strohm
2003-04-09  7:50 ` Eric G. Miller
2003-04-09  8:10   ` Lutz Donnerhacke
2003-04-09 18:23   ` Matthew Heaney
2003-04-09 17:42 ` Matthew Heaney
2003-04-09 21:06   ` Randy Brukardt
2003-04-10  8:23   ` Lutz Donnerhacke
2003-04-10 14:09     ` Matthew Heaney
2003-04-10 14:48       ` Hyman Rosen
2003-04-11  6:20         ` Chad R. Meiners
2003-04-11 12:31           ` Hyman Rosen
2003-04-11 18:27             ` Chad R. Meiners
2003-04-11  7:35         ` Phil Thornley
2003-04-11 12:05           ` Marin David Condic
2003-04-11 13:19             ` John R. Strohm
2003-04-12 23:09               ` Robert A Duff
2003-04-11 18:47             ` Chad R. Meiners
2003-04-12 23:51         ` Robert A Duff
2003-04-13  5:47           ` Hyman Rosen
2003-04-14  8:05             ` Lutz Donnerhacke
2003-04-10 15:02       ` Lutz Donnerhacke
2003-04-10 15:50         ` Hyman Rosen
2003-04-10 18:32           ` Randy Brukardt
2003-04-11  6:28         ` Chad R. Meiners
2003-04-11  8:11           ` Lutz Donnerhacke
2003-04-11 12:32 ` Rod Chapman [this message]
2003-04-11 14:50   ` Peter Amey
2003-04-11 18:41   ` Matthew Heaney
2003-04-11 21:25     ` Chad R. Meiners
2003-04-12 10:08     ` Peter Amey
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox