comp.lang.ada
 help / color / mirror / Atom feed
* Interfacing Ada to Unix/execl var. arg. list function?
@ 1994-10-13  7:44 Dale Stanbrough
  1994-10-13  9:21 ` David Emery
                   ` (5 more replies)
  0 siblings, 6 replies; 13+ messages in thread
From: Dale Stanbrough @ 1994-10-13  7:44 UTC (permalink / raw)


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;

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!).
#3 seems awfully clunky, esp. as you have to alias all the strings before hand.
#4 is there a better one?



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);
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");

begin
      -- how to do this?
end;
-----------------------------------------------------------
Thanks for any help you can give...

Dale
-------------------------------------------------------------
Dale Stanbrough, RMIT, Melbourne, Australia, dale@rmit.edu.au
GNU Ada 94 (GNAT) => the best $0 you'll ever spend.
Available for DOS, Linux, OS/2, Sun Sparc, Sun Solaris, ...
Coming to a GNU supported platform near you soon...



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var. arg. list function?
  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
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: David Emery @ 1994-10-13  9:21 UTC (permalink / raw)


Gee, Dale is discovering -why- the POSIX/Ada binding is not a direct
analog to C...  
				dave
--
--The preceeding opinions do not necessarily reflect the opinions of
--The MITRE Corporation or its sponsors. 
-- "A good plan violently executed -NOW- is better than a perfect plan
--  next week"                                      George Patton
-- "Any damn fool can write a plan.  It's the execution that gets you
--  all screwed up"                              James Hollingsworth
-------------------------------------------------------------------------



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var. arg. list function?
  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-14 13:55   ` Norman H. Cohen
  1994-10-13 13:31 ` Nicolas Courtel
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 13+ messages in thread
From: Robert Dewar @ 1994-10-13 12:22 UTC (permalink / raw)


#2 won't work because attributes can only be applied to names (i.e. it is
a simple case of a syntax error). GNAT does indeed give a confusing
error message:

     6.    v := "abc"'access;
                     |
        >>> binary operator expected

LRM references aren't the issue here, since GNAT would merely point to
some syntax rule about binary operators which would not be the slightest
help. The important thing about error messages is that they have to guess
right what you did wrong. What is happening here is that GNAT has parsed a
primary (the string literal) that cannot possibly be a name, so it doesn't
even consider the possibility of an attribute, and then it flails around
for what might appear.

Clearly what is needed is a decent error message, something like:

     6.    v := "abc"'access;
                |
        >>> attribute prefix must be a name

The RM reference if one was given would simply point to the syntax rule
for attributes showing that the prefix of an attribute must be a name,
so would not add much.

Unless the compiler correctly guesses what you had in mind, no amount of
extra explanation of what it THINKS is the error will help, in fact it will
simply confuse further.

Anyway, I have put this error case on my list of things to look at, and
I would really appreciate if more people would send in cases like this
where GNAT does a poor job of giving error messages -- we can only
improve this if we see examples. I collect/fix my own errors, but I am
disappointed I don't get more complaints/suggestions in this area
-- I guess people have grown accustomed to poor error messages in Ada
compilers -- let's fix that!

Back to the problem at hand. The proper solution is

   execv (pathname, strings_array'(new string'("a"), new string'("bc"), ....))

For problem #2, it is indeed a glitch that to declare a null array
constant you have to provide a junk initialization value for all the
values, except of course there AREN'T any values, so that's a bit
annoying. Of course again you don't need a separate junk variable:

    null_arg_list : constant string_array := (1..0 => new string'(""));

will do fine.

Note: pointers to aggregates certainly make sense at the implementation
level, and at that level we have something called a reference which can
be applied to any expression to get a pointer to that expression. It
would be easy enough to provide this as an extension to Ada, but GNAT
is not (yet) in the language extension business :-)




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var. arg. list function?
  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 13:31 ` Nicolas Courtel
  1994-10-13 19:28 ` Tucker Taft
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Nicolas Courtel @ 1994-10-13 13:31 UTC (permalink / raw)


>>>>> On 13 Oct 1994 07:44:37 GMT, Dale Stanbrough <dale@goanna.cs.rmit.edu.au> said:

|> 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 have written such a binding some time ago : it's called Paradise, is free
software, and you can get it from ftp.cenatls.cena.dgac.fr, in pub/export.
It has not been ported for Gnat yet, but I plan to do so when I have some time.

|> I've got stuck on how to implement Ada calls to the corresponding
|> variable parameter list C functions, specifically execl.

Here's the specification of Paradise's execv call (as execl requires a variable
number of parameters, I have found no clean binding to it):

   type PARAMETER is access STRING;
   type PARAMETER_ARRAY is array (NATURAL range <>) of PARAMETER;

   procedure EXECV (PATH: in STRING; ARGV: in PARAMETER_ARRAY);

An ASCII.nul suffix is added to all the strings in the body, and the C execv is
very happy with them.

For those who are interested, here's the README of Paradise:

--
Paradise is a set of Ada packages intended to provide an interface to the Unix
operating system, and more specifically to the communication routines, that
are accessed via file descriptors. It lets the Ada programmer use files, pipes,
and sockets, as well as signals, error codes, environment variables, etc...,
using an interface that looks as much as possible like the C interface.

Paradise supports multi-tasking: any input or output is blocking for the
calling task only, and not for the entire process.

Paradise is intended to be system-independant and compiler-independant; so far,
it works on four environments:
- SunOS 4.1 (Sparc) and SunAda (Verdix 6.1) compiler
- SunOS 4.1 (Sparc) and TeleSoft 4.1.1 compiler
- HP-UX (HP9000/700) and HP-Ada (Alsys) compiler
- HP-UX (HP9000/700) and Verdix 6.3d compiler

It is known not to work well on SunOS/Alsys, because of problems on signal
handlers;

For people who would like to port it to other environments, informations on
portability are displayed inside the code. A programmer's guide should appear
in future versions.

Send all comments, bug reports, patches to "paradise@cenatls.cena.dgac.fr"

Nicolas Courtel - December 1993

-- 
Nicolas Courtel - courtel@dgac.fr

>>>                    Inside every large program                     <<<
>>>             is a small program struggling to get out              <<<



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var. arg. list function?
  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
  1 sibling, 1 reply; 13+ messages in thread
From: Mark A Biggar @ 1994-10-13 17:37 UTC (permalink / raw)


In article <37j8pd$ovu@gnat.cs.nyu.edu> dewar@cs.nyu.edu (Robert Dewar) writes:
>#2 won't work because attributes can only be applied to names (i.e. it is
>For problem #2, it is indeed a glitch that to declare a null array
>constant you have to provide a junk initialization value for all the
>values, except of course there AREN'T any values, so that's a bit
>annoying. Of course again you don't need a separate junk variable:
>
>    null_arg_list : constant string_array := (1..0 => new string'(""));
>
>will do fine.

Why even go that far? Why not:

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

--
Mark Biggar
mab@wdl.loral.com





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var. arg. list function?
  1994-10-13 17:37   ` Mark A Biggar
@ 1994-10-13 18:46     ` Robert Dewar
  0 siblings, 0 replies; 13+ messages in thread
From: Robert Dewar @ 1994-10-13 18:46 UTC (permalink / raw)


Indeed, Mark, the junk allocation of a null string constant is just that
junk! Just goes to show how you can be lead down the garden path :-)




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var. arg. list function?
  1994-10-13  7:44 Interfacing Ada to Unix/execl var. arg. list function? Dale Stanbrough
                   ` (2 preceding siblings ...)
  1994-10-13 13:31 ` Nicolas Courtel
@ 1994-10-13 19:28 ` Tucker Taft
  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
  5 siblings, 0 replies; 13+ messages in thread
From: Tucker Taft @ 1994-10-13 19:28 UTC (permalink / raw)


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



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var.
  1994-10-13  7:44 Interfacing Ada to Unix/execl var. arg. list function? Dale Stanbrough
                   ` (3 preceding siblings ...)
  1994-10-13 19:28 ` Tucker Taft
@ 1994-10-14 13:55 ` ncohen
  1994-10-17 18:18 ` Interfacing Ada to Unix/execl var. arg. li Bob Gilbert
  5 siblings, 0 replies; 13+ messages in thread
From: ncohen @ 1994-10-14 13:55 UTC (permalink / raw)


Subject: Re: Interfacing Ada to Unix/execl var. arg. list function?

In article <37j8pd$ovu@gnat.cs.nyu.edu>, dewar@cs.nyu.edu (Robert Dewar)
writes: 

|>           Of course again you don't need a separate junk variable: 
|>
|>     null_arg_list : constant string_array := (1..0 => new string'(""));
|>
|> will do fine.

Or simply (1 .. 0 => null).

--
Norman H. Cohen    ncohen@watson.ibm.com



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var. arg. list function?
  1994-10-13 12:22 ` Robert Dewar
  1994-10-13 17:37   ` Mark A Biggar
@ 1994-10-14 13:55   ` Norman H. Cohen
  1 sibling, 0 replies; 13+ messages in thread
From: Norman H. Cohen @ 1994-10-14 13:55 UTC (permalink / raw)


In article <37j8pd$ovu@gnat.cs.nyu.edu>, dewar@cs.nyu.edu (Robert Dewar)
writes: 

|>           Of course again you don't need a separate junk variable: 
|>
|>     null_arg_list : constant string_array := (1..0 => new string'(""));
|>
|> will do fine.

Or simply (1 .. 0 => null).

--
Norman H. Cohen    ncohen@watson.ibm.com



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var. arg. li
  1994-10-13  7:44 Interfacing Ada to Unix/execl var. arg. list function? Dale Stanbrough
                   ` (4 preceding siblings ...)
  1994-10-14 13:55 ` Interfacing Ada to Unix/execl var ncohen
@ 1994-10-17 18:18 ` Bob Gilbert
  1994-10-19  3:30   ` Interfacing Ada to Unix/execl var. arg. list function? Dale Stanbrough
  1994-10-20  4:18   ` Interfacing Ada to Unix/execl var. arg. li S M Ryan
  5 siblings, 2 replies; 13+ messages in thread
From: Bob Gilbert @ 1994-10-17 18:18 UTC (permalink / raw)


In article h9v@goanna.cs.rmit.oz.au, Dale Stanbrough <dale@goanna.cs.rmit.edu.au> () writes:
->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 #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");
->
->begin
->      -- how to do this?
->end;

I don't know all (any of) the details involved with C_execl but...

If it is desired for the arg_list to contain a list of values 
of possibly different types, and you would like to protect the
procedure/function from invalid (wrong type) arguments (maybe
better than just passing an array of addresses to who knows what),
and you don't want to have to overload the function with all the
possible argument lengths, then how about something like:

  -- enumerate all possible argument types
  type ARG is (Arg_1, Arg_2, Arg_3, ... Arg_n, Null_Arg);

  type ARG_RECORD is (Arg_Name : ARG := Null_Arg) is
    record
      case Arg_Name is
        when Arg _1 =>
          Arg_1 : ARG_1_TYPE;
        when Arg_2 =>
          Arg_2 : ARG_2_TYPE;
         .
         .
        when Arg_n =>
          Arg_n : ARG_N_TYPE;
        when Null_Arg => null;
    end record;

  type ARG_LIST is array (NATURAL range <>) of ARG_RECORD;

  Null_Arg_List : constant ARG_LIST(1..0);

  ---------------------------------------------------------
  -- The following procedure (or function) can be invoked as:
  --
  --  C_Excel(My_Path, ARG_LIST'((Arg_1, Data_1),
  --                             (Arg_3, Data_2),
  --                             ...
  --                             (Arg_n, Data_n)));
  ---------------------------------------------------------
  function C_Excel(Path     : System.ADDRESS;
                   Arg_List : ARG_LIST := Null_Arg_List) return Interfaces.c.int is

    type ADDRESS_ARRAY is array (NATURAL range Arg_List'range) of System.ADDRESS;
    Arg_Address_List : ADDRESS_ARRAY;

  begin
    for i in Arg_List'range loop          -- Build Arg_Address_List for C call
      case Arg_List is
          Arg_List(i) := Arg_List(i).Arg_1'address;
        when Arg_2 =>
          Arg_List(i) := Arg_List(i).Arg_2'address;
         .
         .
        when Arg_n =>
          Arg_List(i) := Arg_List(i).Arg_n'address;
        when Null_Arg => null;
      end case;
    end loop;
      .
      .
      .
    return {whatever};
  end C_Excel;

pragma (Disclaimer_On);

  Hope I didn't make too many errors in the above example,
  I didn't get a chance to see if it actually compiles.
  If their are any problems that I didn't account for (like
  maybe the Arg_Address_List does not have a valid lifetime
  or something), or if I'm just completely off base, I'm sure 
  others will correct me.

-Bob




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var. arg. list function?
  1994-10-17 18:18 ` Interfacing Ada to Unix/execl var. arg. li Bob Gilbert
@ 1994-10-19  3:30   ` 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
  1 sibling, 1 reply; 13+ messages in thread
From: Dale Stanbrough @ 1994-10-19  3:30 UTC (permalink / raw)


In article <37uf6e$7ik@theopolis.orl.mmc.com> Bob Gilbert,
rgilbert@orl.mmc.com writes:
>  function C_Excel(Path     : System.ADDRESS;
>                   Arg_List : ARG_LIST := Null_Arg_List) return
Interfaces.c.int is
>
>    type ADDRESS_ARRAY is array (NATURAL range Arg_List'range) of
System.ADDRESS;
>    Arg_Address_List : ADDRESS_ARRAY;
>
>  begin
>    for i in Arg_List'range loop          -- Build Arg_Address_List for C call
>      case Arg_List is
>          Arg_List(i) := Arg_List(i).Arg_1'address;
>        when Arg_2 =>
>          Arg_List(i) := Arg_List(i).Arg_2'address;
>         .
>         .
>        when Arg_n =>
>          Arg_List(i) := Arg_List(i).Arg_n'address;
>        when Null_Arg => null;
>      end case;
>    end loop;
>      .
>      .

The main problem lies in here - how do you assemble the various
arguments into a call to a pragma import'ed C routine?

The only solution appears to be to direct pass parameters via 
aggregates (as your solution suggests) and then call an equivalent
non-variable argument list function (e.g. execl - execv).

The code below works, but I am unsure of whether it is memory safe,
and whether all memory gets reclaimed at the end of the function.


function execv( path    :string;
                argv    :string_array := null_arg_list) return integer is

        C_path  :constant interfaces.c.char_array(1..path'length+1)
                                := interfaces.c.to_C(path);
        type address_array is array(1..argv'length + 1) of system.address;

        C_argv  :address_array;
        index   :integer;

        ------------------------------------------------------------
        function C_execv(       path    :system.address;
                                C_arg_list:system.address)
                                        return interfaces.c.int;
        pragma import(C, C_execv, "execv");
        ------------------------------------------------------------
begin
        -- set up the array of pointers to the strings
        index := 0;
        for i in argv'range loop
                index := index + 1;
                -- can Ada release the memory pointed returned by 
                -- interfaces.c.to_c after the loop (leaving the pointer
                -- pointing at nothing), or will it wait until the end of
                -- the function, or will it never free up the memory?

                C_argv(index) := interfaces.c.to_c(argv(i).all)(0)'address;
        end loop;

        -- append C style null to the end of the array of addresses
        -- (presumes that system.null_address = C style null).

        C_argv(C_argv'last) := system.null_address;

        -- pass the address of the first element of each
        -- parameter, as C expects.

        return integer(C_execv( C_path(1)'address,
                                C_argv(1)'address));
end execv;


Thanks,

Dale

-------------------------------------------------------------
Dale Stanbrough, RMIT, Melbourne, Australia, dale@rmit.edu.au
GNU Ada 94 (GNAT) => the best $0 you'll ever spend.
Available for DOS, Linux, OS/2, Sun Sparc, Sun Solaris, ...
Coming to a GNU supported platform near you soon...



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var. arg. li
  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  4:18   ` S M Ryan
  1 sibling, 0 replies; 13+ messages in thread
From: S M Ryan @ 1994-10-20  4:18 UTC (permalink / raw)


: ->I've got stuck on how to implement Ada calls to the corresponding
: ->variable parameter list C functions, specifically execl.
: ->
: ->--      int execl(path, arg0 [ , arg1,...  , argn ] (char *)0)
: ->--      char *path, *arg0, *arg1, ..., *argn;

You can finesse it by only providing execv, execve, and execvp.
-- 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __________________________________
| | | | | | | | | | | | | | | | | | | | | smryan@netcom.com	PO Box 1563
| | | | | | |G|A|T|E| |1| | | | | | | | |             Cupertino, California
|E|e|t|i|i|n| |s| |a|e|2| | | | | | | | |_(xxx)xxx-xxxx_______________95013
|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|____(coming soon: a new signature)



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing Ada to Unix/execl var. arg
  1994-10-19  3:30   ` Interfacing Ada to Unix/execl var. arg. list function? Dale Stanbrough
@ 1994-10-20 12:42     ` Bob Gilbert
  0 siblings, 0 replies; 13+ messages in thread
From: Bob Gilbert @ 1994-10-20 12:42 UTC (permalink / raw)


In article ioq@goanna.cs.rmit.oz.au, Dale Stanbrough <dale@goanna.cs.rmit.edu.au> () writes:
->
->The main problem lies in here - how do you assemble the various
->arguments into a call to a pragma import'ed C routine?
->
->The only solution appears to be to direct pass parameters via 
->aggregates (as your solution suggests) and then call an equivalent
->non-variable argument list function (e.g. execl - execv).
->
->The code below works, but I am unsure of whether it is memory safe,
->and whether all memory gets reclaimed at the end of the function.
->
->
->function execv( path    :string;
->                argv    :string_array := null_arg_list) return integer is
->
->        C_path  :constant interfaces.c.char_array(1..path'length+1)
->                                := interfaces.c.to_C(path);
->        type address_array is array(1..argv'length + 1) of system.address;
->
->        C_argv  :address_array;
->        index   :integer;
->
->        ------------------------------------------------------------
->        function C_execv(       path    :system.address;
->                                C_arg_list:system.address)
->                                        return interfaces.c.int;
->        pragma import(C, C_execv, "execv");
->        ------------------------------------------------------------
->begin
->        -- set up the array of pointers to the strings
->        index := 0;
->        for i in argv'range loop
->                index := index + 1;
->                -- can Ada release the memory pointed returned by 
->                -- interfaces.c.to_c after the loop (leaving the pointer
->                -- pointing at nothing), or will it wait until the end of
->                -- the function, or will it never free up the memory?
->
->                C_argv(index) := interfaces.c.to_c(argv(i).all)(0)'address;
->        end loop;
->
->        -- append C style null to the end of the array of addresses
->        -- (presumes that system.null_address = C style null).
->
->        C_argv(C_argv'last) := system.null_address;
->
->        -- pass the address of the first element of each
->        -- parameter, as C expects.
->
->        return integer(C_execv( C_path(1)'address,
->                                C_argv(1)'address));
->end execv;
->
->
->Thanks,
->
->Dale

Does interfaces.c.to_c cause memory to be allocated?

If not, then there is no problem since the array C_argv is created
on the calling stack and released upon exit from the function execv.

-Bob





^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~1994-10-20 12:42 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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