comp.lang.ada
 help / color / mirror / Atom feed
From: stt@spock.camb.inmet.com (Tucker Taft)
Subject: Re: Interfacing Ada to Unix/execl var. arg. list function?
Date: Thu, 13 Oct 1994 19:28:35 GMT
Date: 1994-10-13T19:28:35+00:00	[thread overview]
Message-ID: <CxMM3o.LE9@inmet.camb.inmet.com> (raw)
In-Reply-To: 37ioh5$h9v@goanna.cs.rmit.oz.au

In article <37ioh5$h9v@goanna.cs.rmit.oz.au>,
Dale Stanbrough  <dale@goanna.cs.rmit.edu.au> wrote:

>I am currently trying to develop a simple Ada/Unix binding (not Posix!)
>that will allow students to use the packages with a minimum of fuss.
>(i.e. reading the Unix man page/Unix programming text would give them
>a fair idea of how to use the Ada version).
>
>I've got stuck on how to implement Ada calls to the corresponding
>variable parameter list C functions, specifically execl.
>
>Also the solutions I have written currently look clunky. I was wondering if 
>there was a better way to implement these features.
>
>
>
>Problem #1.
>-----------
>Passing in a list of variable length strings...
>
>The possible options for passing in strings would be...
>
>type string_ptr is access all string;
>type string_array is array(natural range <>) of string_ptr;

If you change "string_ptr" to be:
   type string_ptr is access constant string;

Then allocators for string_ptr can be done statically.

>then...
>
>#1 ...execv(pathname, strings'("a","bb","cccc"));
>#2 ...execv(pathname, strings_array'("a"'access, "bb"'access, "ccc"'access));
>#3 ...execv(pathname, strings_array'(a'access,b'access,c'access));
>#4 ...execv(pathname, ?);
>
>#1 won't work because arrays elements have to be the same size
>#2 won't work because I don't know why ?:-/ (I wish Gnat gave me LRM ref's!).

A string literal is not a name, and attributes are only allowed
on names.

>#3 seems awfully clunky, esp. as you have to alias all the strings before hand.
>#4 is there a better one?

Yes, I would recommend:

    execv(pathname, 
      (new String'("a"), new String("bb"), new String("cccc")));

For convenience you could define an inline function:

    function "+"(S : String) return String_Ptr;
    pragma Inline("+");
    function "+"(S : String) return String_Ptr is
	pragma Inline("+");
    begin
       return new String'(S);
    end "+";

which would reduce this to:
    execv(pathname, (+"a", +"bb", +"cccc"));

Alternatively, you could also define some operators which
produce String_Arrays directly, eliminating the need for
the explicit aggregate (this kind of operator overloading
is not necessarily considered "good form" by all, perhaps
because it can hinder readability if overdone):

    function "+"(Left : String_Array; Right : String) 
      return String_Array;
    function "+"(Right : String) return String_Array;
    pragma Inline("+");

    function "+"(Left : String_Array; Right : String) 
      return String_Array is
    begin
	return Left & new String'(Right);
    end "+";

    function "+"(Right : String) return String_Array is
    begin
        return (1 => new String'(Right));
    end "+";

With the above, the call on execv would reduce to:

   execv(pathname, "a" + "bb" + "cccc");

>Problem #2.
>-----------
>Defining a constant null array seems to require the declaration of a
>superfluous variable just to make the compiler happy...
>
>------------------------------------------------------------
>package unix is
>        type string_ptr is access all string;
>        type string_array is array(natural range <>) of string_ptr;
>
>        null_arg_list   :constant string_array;
>
>        function execl( path    :string;
>                        arg_list:string_array := null_arg_list)
>                        return integer;
>
>private
>
>        dummy   :aliased constant string := "";   --?? superfluous?
>        null_arg_list   :constant string_array := (1..0 => dummy'access);

No, you can use null instead:

        null_arg_list : constant String_Array := (1 .. 0 => null);

>end unix.process;
>------------------------------------------------------------

>Problem #3.
>-----------
>How to specify and pass in a variable list of pointers to a C program.
>(Yes, I know we've been down this path before, but generally w.r.t.
>printf, which has varying types of parameters, as well as number).
>
>-----------------------------------------------------------
>-- Calling profile for execl in C.
>--
>--      int execl(path, arg0 [ , arg1,...  , argn ] (char *)0)
>--      char *path, *arg0, *arg1, ..., *argn;
>--
>
>function execl( path            :string;
>                arg_list        :string_array) return integer is
>
>        ---------------------------------------------
>        function C_execl( path      :system.address;
>                          C_arg_list:               --?? What type here?
>                          return interfaces.c.int;
>        pragma import(C, C_execl, "execl");

It will probably work to have a bunch of separate 
functions all with the same external_name,
with different numbers of parameters.

E.g.:

   function C_execl(Path : System.Address; C_arg1 : System.Address);
   function C_execl(Path : System.Address; 
     C_arg1, C_arg2 : System.Address);
   function C_execl(Path : System.Address; 
     C_arg1, C_arg2, C_arg3 : System.Address);
... etc.
   pragma Import(C, C_execl, "execl");

>begin
>      -- how to do this?

Actually, execl is normally implemented in terms of execv, so
I am a little surprised you would try to hook up to execl here.
But if you really wanted to, you would have to have
a case statement:

    case arg_list'Length is
       when 1 => 
         return Integer(c_execl(path'address, c_arg_list(1)'address));
       when 2 =>
         return Integer(c_execl(path'address, 
            c_arg_list(1)'address, c_arg_list(2)'address));
      ...
       when others =>
         -- complain
    end case;

However, as mentioned above, the right solution for this
particular case seems to be to build up an array of
addresses, and then pass that to C's execv, instead of
calling C's execl.

In fact, given the way of handling variable-length lists
in Ada, there seems no reason to distinguish between execv
and execl.

>end;
>-----------------------------------------------------------
>Thanks for any help you can give...
>
>Dale
>-------------------------------------------------------------
>Dale Stanbrough, RMIT, Melbourne, Australia, dale@rmit.edu.au

-Tucker Taft   stt@inmet.com
Intermetrics, Inc.
Cambridge, MA  02138



  parent reply	other threads:[~1994-10-13 19:28 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1994-10-13  7:44 Interfacing Ada to Unix/execl var. arg. list function? Dale Stanbrough
1994-10-13  9:21 ` David Emery
1994-10-13 12:22 ` Robert Dewar
1994-10-13 17:37   ` Mark A Biggar
1994-10-13 18:46     ` Robert Dewar
1994-10-14 13:55   ` Norman H. Cohen
1994-10-13 13:31 ` Nicolas Courtel
1994-10-13 19:28 ` Tucker Taft [this message]
1994-10-14 13:55 ` Interfacing Ada to Unix/execl var ncohen
1994-10-17 18:18 ` Interfacing Ada to Unix/execl var. arg. li Bob Gilbert
1994-10-19  3:30   ` Interfacing Ada to Unix/execl var. arg. list function? Dale Stanbrough
1994-10-20 12:42     ` Interfacing Ada to Unix/execl var. arg Bob Gilbert
1994-10-20  4:18   ` Interfacing Ada to Unix/execl var. arg. li S M Ryan
replies disabled

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